赞
踩
为什么要认证
认证是为了保护系统的隐私数据和资源。
什么是认证
判断用户的身份是否合法的过程。
常见的认证方式有哪些
什么是会话
会话就是系统为了保持当前用户的登录状态所提供的机制。
常见的会话机制
两种实现方式的对比
基于 session 的认证方式由 Servlet 规范定制,服务器要存储 session 信息要占用内存资源,客户端需要支持 cookie;
基于 token 的认证方式则一般不需要服务器存储 token,并且不限制客户端的存储方式。
如今移动互联网时代更多类型的客户端需要接入系统,系统多是采用前后端分离的架构实现,所以基于 token 的方式更适合。
基于 session 的认证方式如下图
基于 session 的认证交互流程
用户认证成功后,在服务端生成用户相关的数据保存在 session(当前会话) 中,发给客户端 的 session_id 存放到 cookie 中, 这样用户客户端请求时带上 session_id 就可以验证服务端是否存在 session 数据,以此完成用户的合法校验,当用户退出系统或 session 过期销毁时,客户端的 session_id 也就无效了。
基于 token 的认证方式如下图
基于 token 的认证交互流程
用户认证成功后,服务端生成一个 token 发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到 token 通过校验后即可确认用户身份。
为什么要授权
是为了更细粒度的对隐私数据进行划分。
什么是授权
授权是用户认证通过根据用户权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。
授权可以简单的理解为 Who 对 What(Which) 进行 How 操作。
关键的概念
主体、资源、权限关系如下图
主体、角色、权限关系如下图
如何实现授权?
业界通常基于 RBAC 的实现授权。
基于角色的访问控制
RBAC 基于角色的访问控制 (Role Based Access Control) 是按角色授权。
例如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等,访问控制流程如下:
当需要修改角色的权限时就需要修改授权相关的代码,系统的可扩展性差。
基于资源的访问控制
RBAC 基于资源的访问控制 (Resource Based Access Control) 是按资源(或权限)进行授权。
优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也不需要修改授权代码,系统的可扩展性强。
Spring Security 是一个能够为基于 Spring 的企业级应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是 Spring 生态系统中的一员,因此它伴随整个 Spring 生态系统不断修正、升级,在 Spring Boot 项目中加入 Spring Security 更是十分简单,使用 Spring Security 减少了为企业系统安全控制编写大量重复代码的工作。
Spring Security 所解决的问题就是安全访问控制,而安全访问控制功能其实就是对所有进入系统的请求进行拦截,校验每个请求是否能够访问它所期望的资源。一般实现的方式有 Filter 和 AOP。Spring Security 对 web 资源的保护是靠 Filter 实现的。
当初始化 Spring Security 时,会创建一个名为 SpringSecurityFilterChain 的 Servlet 过滤器,类型为 org.springframework.security.web.FilterChainProxy, 它实现了 javax.servlet.Filter, 因此外部的请求会经过此类。
Spring Security 过滤器链结构
FilterChainProxy 是一个代理,真正起作用的是 FilterChainProxy 中 SecurityFilterChain 所包含的各个 Filter,同时这些 Filter 作为 bean 被 Spring 管理,它们是 Spring Security 的核心,各有各的职责,但它们并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了认证管理器 (AuthenticationManager)和决策管理器 (AccessDecisionManager) 进行处理。
FilterChainProxy相关类的UML
Spring Security 功能的实现主要是由一系列的过滤器链相互配合完成
AuthenticationManager 接口(认证管理器) 是认证相关的核心接口,也发起认证的出发点,他的实现类为 ProviderManager。而 Spring Security 支持多种认证方式,因此 ProviderManager 维护着一个 List<AuthenticationProvider> 列表,存放多种认证方式,最终实际的认证工作是由 AuthenticationProvider 完成的。
Web 表单的对应的 AuthenticationProvider 实现类为 DaoAuthenticationProvider, 它的内部又维护着一个 UserDetailsService 负责 UserDetails 的获取。最终 AuthenticationProvider 将 UserDetails 填充至 Authentication。
认证核心组件的大体关系
AuthenticationProvider 处理了认证的逻辑,它会去比对 UserDetailsService 提取到的用户密码和用户提供的密码是否一致。认证通过会将 Authentication(UsernamePasswordAuthenticationToken实现) 返回。
UserDetailsService 负责根据用户名提取用户信息 UserDetails(包含密码)
可以通过将自定义的 UserDetailsService 公开为 spring bean 来定义自定义身份验证。
常见的 PasswordEncoder
Spring Security 可以通过 http.authorizeRequests() 对 web 请求进行授权保护。Spring Security 使用标准 Filter 建立了对 web 请求的拦截,最终实现对资源的授权访问。
Spring Security 的授权流程
授权相关主要的过滤器
授权流程
AccessDecisionManager 采用投票的方式来确定是否能够访问受保护资源的权限。
SpringSecurity 内置了三个基于投票的 AccessDecisionManager实现类, 默认使用 AffirmativeBased
AffirmativeBased 执行逻辑
ConsensusBased 执行逻辑
UnanimousBased 执行逻辑
Spring Security 也内置了一些投票者实现类
用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保存在会话中。
Spring Security 提供会话管理,认证通过后将身份信息放入 SecurityContextHolder 上下文,SecurityContext 与当前线程进行绑定,方便用户获取用户身份。
会话机制
默认情况下,Spring Security 会为每个登录成功的用户新建一个 session, 就是 IfRequired
stateless 适用于 Rest API 及其无状态认证机制。
安全会话cookie
授权的方式包括 web 授权和方法授权,web 授权是通过 url 拦截进行实现,方法授权是通过方法拦截进行授权。他们都会调用 accessDecisionManager 进行授权决策,若为 web 授权则拦截器为 FilterSecurityInterceptor;若为方法授权则拦截器为 MethodSecurityInterceptor。如果同时通过 web 授权和方法授权则先执行 web 授权,执行方法授权。最后决策通过,则允许访问资源,否则将禁止访问。
授权方式
推荐使用基于资源的授权。
配置权限拦截时,应该将具体的权限拦截放到正则表达式的拦截前。
http.authorizeRequests() 保护 URL 常用的方法
从 Spring Security 2.0 版本开始,它支持服务层方法的安全性的支持
可以在任何 @Configuration 实例上使用 @EnableGlobalMethodSecurity 注释来启用基于注解的安全性。
@Secured 使用
@PreAuthorize 使用
随着软件环境和需求的变化,软件的架构由单体结构演变为分布式架构,具有分布式架构的系统叫分布式系统。
分布式系统的运行通常依赖网络,它将单体结构的系统分为若干服务,服务之间通过网路交互来完成用户的业务,当前流行的微服务架构就是分布式系统架构。
分布式系统架构
分布式系统的特点
分布式系统的每个服务都会有认证、授权的需求,如果每个服务都实现一套认证授权逻辑会非常冗余,考虑分布式系统共享性的特点,需要由独立的认证服务处理系统认证授权的请求;考虑分布式系统开放性的特点,不仅对系统内部服务提供认证,对第三方系统也要提供认证。
分布式认证的需求总结:
统一认证授权
提供独立的认证服务,统一处理认证授权。
无论是不同类型的用户,还是不同种类的客户端(web端、H5、APP),均采用一致的认证、权限、会话机制,实现统一认证授权。
要实现统一则认证方式必须可扩展,支持各种认证需求,比如:用户名密码认证、短信验证码、二维码、人脸识别等认证方式,并可以非常灵活的切换。
应用接入认证
应提供扩展和开放的能力,提供安全的系统对接机制,并可开放部分 API 给接入第三方使用,一方应用(内部系统服务)和三方应用(第三方应用)均采用统一机制接入。
1.基于 Session 的认证方式
总的来说,基于 session 认证的认证方式,可以更好的在服务端对会话进行控制,且安全性较高,但是 session 机制方式基于 cookie,在复杂多样的移动客户端上不能有效的使用,并且无法跨域,另外随着系统的扩展需提高 session 的复制、黏贴及存储的容错性。
2.基于token的认证方式
基于 token 的认证方式,服务端不用存储认证数据,易维护扩展性强,客户端可以把token存在任意地方,并且可以实现 web 和 app 统一认证机制。其缺点也很明显,token 由于自包含信息,因此一般数据量较大,而且每次请求都需要传递,因此比较占带宽,另外,token的签名操作也会给 cpu 带来额外的处理负担。
根据选型的分析,决定采用基于 token 的认证方式,它的优点是:
分布式系统认证技术方案
分布式系统认证流程描述
流程所涉及到认证服务、网关这两个组件职责如下:
OAuth (开放授权) 是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。
OAuth 2.0 是 OAuth 协议的延续版本,但不向后兼容 OAuth 1.0,即完全废止 OAuth 1.0。
OAuth2.0 认证过程
OAuth 2.0 角色
现在还有一个问题,服务提供商能允许随便一个客户端就接入到他们的授权服务器吗?答案是否定的,服务提供商会给准入的接入方一个身份,用于接入时的凭据:
因此准确的来说,授权服务器对两种 OAuth2.0 中的两个角色进行认证授权,分别是 资源拥有者、客户端。
Spring-Security-OAuth2.0 是对 OAuth2.0 的一种实现,并且和 Spring Security 相辅相成,与 Spring Cloud 体系的集成也非常便利。
OAuth 2.0 的服务提供方涵盖两个服务:
授权服务(Authorization Server,也叫认证服务)应包含对接入端以及用户的合法性进行验证并颁发 token 等功能。对令牌的请求端点由 Spring MVC 控制器实现,下面是配置一个认证服务必须要 实现的 endpoint:
资源服务(Resource Server):应包含对资源的保护功能,对非法请求进行拦截,对请求中 token 进行解析鉴权等,下面的过滤器用于实现 OAuth 2.0 资源服务
认证流程
Spring Cloud Alibaba 集成 Spring Security OAuth2.0源码
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。