框架阶段七:SpringSecurity
🧑🎓 个人主页:花棉袄
📖 本章内容:【Spring Security OAuth2.0认证授权】
📢 版权: 本文由【花棉袄】原创 💝在 CSDN 首发 💝 需要转载请联系博主
🍵Spring Security简介
- Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架
- 它是保护基于 Spring 的应用程序的事实标准
- Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架
- 像所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义需求
- 快速入门:🚀Spring Security
🍑认证授权概念
1️⃣什么是认证
- 认证:用户认证就是判断一个用户的身份是否合法的过程,用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问
- 常见的用户身份认证方式有:用户名密码登录,二维码登录,手机短信登录,指纹人脸识别认证等方式
🍑 认证机制
2️⃣什么是会话
- 用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保证在会话中
- 会话就是系统为了保持当前用户的登录状态所提供的机制,常见的有基于session方式、基于token方式等
3️⃣什么是授权
-
认证是为了保证用户身份的合法性
-
授权则是为了更细粒度的对隐私数据进行划分
-
授权是在认证通过后发生的,控制不同的用户能够访问不同的资源
-
授权: 授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问
4️⃣授权数据模型
🍑 授权认证流程
🍑 主体-资源-权限关系
- 用户对资源进行权限操作
- 管理员对用户进行删除操作
🍑 最小数据模型
5️⃣RBAC授权方式
🍑 方式一:RBAC基于角色的访问控制
- Role-Based Access Control:是按角色进行授权
- 比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等
- 缺点:查询工资权限需要的角色发生变化需要更改授权代码,系统扩展性差
🍑 方式二:RBAC基于资源的访问控制
- Resource-Based Access Control:是按资源(或权限)进行授权
- 比如:用户必须具有查询工资权限才可以查询员工工资信息等
- 优点:系统设计时定义查询工资权限标识,即使查询工资权限需要的角色发生变化也不需要更改授权代码,系统扩展性强
🍎其他认证授权方案
1️⃣基于Session认证授权
🍑 基于session的认证方式如下图
- 它的交互流程是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中
- 发给客户端的sesssion_id 存放到
cookie
中,这样用户客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据 - 以此完成用户的合法校验,当用户退出系统或session过期销毁时,客户端的session_id也就无效了
🍎 基于Session的认证实现
- 登录时实现会话
- 退出实现:退出登录时使session失效
- 授权实现:RBAC基于资源的访问控制
在实体中定义一个权限标识,当用户由此标识时通过拦截器放行之后就可以访问资源(要配置拦截规则
)
🍎 基于Session的认证总结
2️⃣基于Token的认证
🕰️ 基于Token的认证方式如下图
- 他的交互是:用户认证成功之后,服务端生成token发送给客户端
- 客户端可以放到
cookie
或者localStorage
等存储中,每次请求带上token - 服务端收到token通过验证后即可确定用户身份
👉🏽简单示例:SpringBoot-JWT实现登陆验证
3️⃣分布式认证
- 在分布式的环境下,基于session的认证会出现一个问题,每个应用服务都需要在session中存储用户身份信息,通过负载均衡将本地的请求分配到另一个应用服务需要将session信息带过去,否则会重新认证
- 👉🏽 分布式Session-解决登录问题
🍏Spring Security原理
1️⃣回顾Filter
- Spring Security 的 Servlet 支持是基于 Servlet的,所以先大致Filter了解一下Filters的作用是有帮助的
- Filter下图显示了单个 HTTP 请求的处理程序的典型分层
- 客户端向应用程序发送一个请求,容器创建一个FilterChain包含Filters
- 并且Servlet应该HttpServletRequest根据请求 URI 的路径处理的
- 在 Spring MVC 应用程序中,Servlet它是DispatcherServlet最多一个Servlet可以处理单个HttpServletRequestand和HttpServletResponse
🍏不止一个Filter可用于
- 防止下游Filters 或Servlet被调用。在这种情况下,Filter通常会编写HttpServletResponse
- 修改下游使用的HttpServletRequestor和HttpServletResponseFilterServlet
🍏 FilterChain使用示例
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
2️⃣安全过滤链
- SecurityFilterChainFilterChainProxy使用它来确定Filter应该为此请求调用哪些 Spring Security
- FilterChainProxy可以用来确定SecurityFilterChain应该使用哪个。这允许为应用程序的不同部分提供完全独立的配置
-
中的安全过滤器通常SecurityFilterChain是 Bean,但它们是使用FilterChainProxy而不是DelegatingFilterProxy注册的
-
👉🏽Security Filters
3️⃣Security认证流程
-
1.用户提交用户名、密码被SecurityFilterChain中的UsernamePasswordAuthenticationFilter 过滤器获取到,封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类
-
2.然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证
-
3.认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除) Authentication 实例。
-
4.SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中
-
可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它的实现类为ProviderManager
-
而Spring Security支持多种认证方式,因此ProviderManager维护着一个List 列表,存放多种认证方式,最终实际的认证工作是由AuthenticationProvider完成的
-
知道web表单的对应的AuthenticationProvider实现类为DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取
-
最终AuthenticationProvider将UserDetails填充至Authentication
4️⃣Security授权流程
Spring Security可以通过 http.authorizeRequests() 对web请求进行授权保护。SpringSecurity使用标准Filter建立了对web请求的拦截,最终实现对资源的授权访问
拦截请求,已认证用户访问受保护的web资源将被SecurityFilterChain中的 FilterSecurityInterceptor 的子类拦截。
获取资源访问策略,FilterSecurityInterceptor会从 SecurityMetadataSource 的子类DefaultFilterInvocationSecurityMetadataSource 获取要访问当前资源所需要的权限Collection 。SecurityMetadataSource其实就是读取访问策略的抽象,而读取的内容,其实就是我们配置的访问规则。
最后,FilterSecurityInterceptor会调用 AccessDecisionManager 进行授权决策,若决策通过,则允许访问资源,否则将禁止访问。