日常bb 日常bb
首页
文章
笔记
冥思
其他
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

日常bb

想起来全是问题,做起来才有答案。
首页
文章
笔记
冥思
其他
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Redis

  • Spring

    • 基础使用

    • Spring Security

      • Spring Security学习总结
      • Spring Security
        • 核心功能
        • 基本原理
        • 表单认证
          • 源码分析
        • 认证的结果如何在请求间共享
        • 授权流程
      • Spring Security OAuth2
      • 实战单体应用(认证授权服务+资源服务)
      • 实战模块化(认证授权服务+资源服务)
      • Spring Security OAuth2自定义授权模式
    • 收藏

  • 工具

  • 概念

  • 容器

  • 实战

  • 文章
  • Spring
  • Spring Security
rcbb
2022-10-02
目录

Spring Security

# Spring Security

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。

它是保护基于Spring的应用程序的官方标准。毕竟是全家桶套餐中的一员。Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。 像所有Spring项目一样,Spring Security的真正强大之处在于它可以轻松扩展以满足自定义需求。

# 核心功能

  1. 认证(你是谁)
  2. 授权(你能干啥)
  3. 攻击防护(防止伪造身份)

# 基本原理

Spring Security基本原理图

上面是Spring Security的基本原理图,最右边就是我们的Controller接口,前面的所有都是过滤器。

简单理解:Spring Security就是一组过滤器,它的核心也就是这样的一条过滤链,访问的所有请求都会经过 Spring Security 的过滤器。

过滤器链上有很多的过滤器,它们的作用就是用来校验用户的身份,每一个过滤器负责处理一种认证方式。

比如:http.formLogin()对应着UsernamePasswordAuthenticationFilter过滤器。
比如:http.httpBasic()对应着BasicAuthenticationFilter过滤器。

请求到达过滤器时,如UsernamePasswordAuthenticationFilter这个过滤器时,就会触发当前请求是否是一个登陆请求,判断请求中是否携带用户名和密码等。如果符合条件,那么过滤器就会试图去登陆,若是不满足条件,就会下发给下一个过滤器。

例如UsernamePasswordAuthenticationFilter下一个过滤器是BasicAuthenticationFilter。到达BasicAuthenticationFilter后又会判断是否触发当前过滤器的条件,如请求头中是否携带Basic 登陆的信息,如果有就会尝试解码和登陆。

其他自定义过滤器也是同样的逻辑,按照这个流程一个个的往下走。

如果在某个过滤器上认证成功后会在请求上做一个标记,用来表示当前这个请求的用户授权成功了。

ExceptionTranslationFilter

ExceptionTranslationFilter异常转换过滤器位于整个过滤链的后方,用来转换整个链路中出现的异常,将其转化,顾名思义,转化以意味本身并不处理。

一般其只处理两大类异常:

  • AccessDeniedException访问异常;
  • AuthenticationException认证异常;

这个过滤器非常重要,因为它将Java中的异常和HTTP 的响应连接在了一起,这样在处理异常时,我们不用考虑密码错误该跳到什么页面,账号锁定该如何,只需要关注自己的业务逻辑,抛出相应的异常便可。

如果该过滤器检测到AuthenticationException,则将会交给内部的AuthenticationEntryPoint去处理,如果检测到AccessDeniedException,需要先判断当前用户是不是匿名用户,如果是匿名访问,则和前面一样运行AuthenticationEntryPoint,否则会委托给AccessDeniedHandler去处理,而AccessDeniedHandler的默认实现,是AccessDeniedHandlerImpl。

所以ExceptionTranslationFilter内部的AuthenticationEntryPoint是至关重要的,顾名思义:认证的入口点。

已注销-ExceptionTranslationFilter详解 (opens new window)

FilterSecurityInterceptor

走过前面所有的过滤器后最后会来到FilterSecurityInterceptor,这个过滤器是整个 Spring Security 过滤器链上的最后一环,它能够决定请求能不能访问 API 请求。

FilterSecurityInterceptor从SecurityContextHolder中获取Authentication对象,然后比对用户拥有的权限和资源所需的权限。前者可以通过Authentication对象直接获得,而后者则需要引入我们之前一直未提到过的两个类:SecurityMetadataSource、AccessDecisionManager。

已注销-FilterSecurityInterceptor详解 (opens new window) 银河架构师-FilterSecurityInterceptor详解 (opens new window)

# 表单认证

程序员劝退师-TAO-SpringSecurity表单认证 (opens new window)

# 源码分析

Spring Security认证流程

AuthenticationManager自己并不包含验证的逻辑,它的作用是用来管理AuthenticationProvider。

getProviders()会拿到整个系统中所有实现AuthenticationProvider的实现类,这里上面提到的AuthenticationManager就是来收集并管理所有AuthenticationProvider的实现类,这里就会循环挨个去比对上面AuthenticationToken类型。

不同的Provider支持的Authentication类型是不一样的,根据传入的Authentication类型这里会挑出一个进行校验处理。

程序员劝退师-TAO-SpringSecurity表单登录流程源码分析 (opens new window)

# 认证的结果如何在请求间共享

认证结果共享

程序员劝退师-TAO-SpringSecurity认证的结果在请求间共享 (opens new window)

# 授权流程

Spring Security真正判断请求能否通过是在FilterSecurityInterceptor过滤器中处理的,如果请求不能通过的话就会根据不同的原因抛出异常,抛出异常以后就会由ExceptionTranslationFilter这个过滤器接收处理。

但有一个特殊的过滤器AnonymousAuthenticationFilter

AnonymousAuthenticationFilter

AnonymousAuthenticationFilter中的逻辑比较简单,就是判断当前的SecurityContextHolder中是否有authentication,是否等于null。

这里的判断实际上就在在判断前面的过滤器是否完成身份的认证,或者在Session中拿到身份的证信息。

如果前面的过滤器一个都没认证的话,那么就会创建一个authentication然后set到SecurityContextHolder中,这里放的并不是认证成功后的用户信息,而是一个字符串anonymousUser。

在Spring Security中,AnonymousAuthenticationFilter是所有认证过滤器的最后一个,也就是不管你前面有没有身份认证成功,SecurityContextHolder中一定是会放一个authentication的。如果前面的过滤器认证成功了,那么放的就是用户身份信息,如果一个都没成功,那么就是一个字符串anonymousUser。

授权流程

核心:FilterSecurityInterceptor、AccessDecisionManager、AccessDecisionVoter。

FilterSecurityInterceptor:它是授权的主入口。

AccessDecisionManager:访问决定的管理者,是一个接口,它有一个抽象实现AbstractAccessDecisionManager和三个具体实现AffirmativeBased、ConsensusBased、UnanimousBase。它也管理者一组AccessDecisionVoter。

AccessDecisionVoter:从名字就能看出它是做投票的。

当AccessDecisionManager收到一个请求时这一组AccessDecisionVoter会根据自己的逻辑判断这个请求时过还是不过。
判断有三套逻辑:

  • AffirmativeBased:不管有多少个AccessDecisionVoter投不过,只要有一个投通过,那么请求就可以访问。(Spring Security的默认实现逻辑)
  • UnanimousBased:不管有多少个AccessDecisionVoter投通过,只要有一个投不通过,那么请求就不可以访问。
  • ConsensusBased:判断通过的AccessDecisionVoter多还是不通过的多,哪个多就是哪个。

在判断一个请求能不能过需要两块数据:ConfigAttribute、Authentication。

ConfigAttribute

请求的权限信息ConfigAttribute。例:a请求需要什么权限,b请求需要什么权限。

请求到达FilterSecurityInterceptor时就会把这个请求路径所需的权限读出来,封装成一组ConfigAttribute对象。

Authentication

Authentication实际上就是当前请求的用户的权限信息,也就是当前用户有哪些权限,这个信息就是封装在Authentication里。


#Spring Security
上次更新: 10/7/2022
Spring Security学习总结
Spring Security OAuth2

← Spring Security学习总结 Spring Security OAuth2→

最近更新
01
Sign in with Apple(苹果授权登陆)
12-29
02
Nacos容器化
11-11
03
好用的截图工具
11-10
更多文章>
Theme by Vdoing | Copyright © 2021-2022 日常bb | 鄂ICP备17023998号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式