深入浅出Spring Security(五):认证和授权的过程

2,745 阅读3分钟

上篇回顾

上篇介绍了HttpSecurity如何建造过滤器链,本文主要介绍几个主要的过滤器。

认证过滤器 UsernamePasswordAuthenticationFilter

参数有username,password的,走UsernamePasswordAuthenticationFilter,提取参数构造UsernamePasswordAuthenticationToken进行认证,成功则填充SecurityContextHolder的Authentication

UsernamePasswordAuthenticationFilter实现了其父类AbstractAuthenticationProcessingFilter中的attemptAuthentication方法。这个方法会调用认证管理器AuthenticationManager去认证。

attemptAuthentication

AbstractAuthenticationProcessingFilter中的doFilter()方法,会判断每个请求是否需要认证。
不需要认证的请求直接放行,需要的认证的会被拦下。

doFilter
requiresAuthentication

判断是否需要认证是怎么做的呢?
其实是我们在调用httpSecurity.formLogin().permitAll()时设置的。

formLogin

FormLoginConfigurer

UsernamePasswordAuthenticationFilter

AbstractAuthenticationProcessingFilter

ProviderManager是认证管理器AuthenticationManager的默认实现
通过提供不同的AuthenticationProvider实现类,可以通过多种方式进行认证
其内部会调用authenticate(Authentication authentication)遍历providers,调用provider.authenticate()来尝试认证
我们可以实现AuthenticationProvider接口,重写authenticate()方法,来查询数据库对用户名密码做认证

ProviderManager

PS: 上面的parent其实就是存放的我们自定义编写的provider的认证管理器。这里就不贴出来了

认证过滤器 BasicAuthenticationFilter

header里头有Authorization,而且value是以Basic开头的,则走BasicAuthenticationFilter,提取参数构造UsernamePasswordAuthenticationToken进行认证,成功则填充SecurityContextHolder的Authentication

BasicAuthenticationFilter

认证过滤器 AnonymousAuthenticationFilter

给没有登陆的用户,填充AnonymousAuthenticationTokenSecurityContextHolderAuthentication

AnonymousAuthenticationFilter

授权过滤器 AbstractSecurityInterceptor

默认的过滤器是FilterSecurityInterceptor,继承了AbstractSecurityInterceptor实现了Filter接口
我们一般直接继承这个过滤器或者继承他的父类,自定义一个AuthorizeSecurityInterceptor
目的是为了注入自定义的授权管理器AccessDecisionManager、和权限元数据FilterInvocationSecurityMetadataSource

FilterSecurityInterceptor是在WebSecurityConfigurerAdapterinit()里配置的

FilterSecurityInterceptor中的doFilter()会调用super.beforeInvocation(fi)方法,内部调用授权管理器做授权

AuthorizeSecurityInterceptor

doFilter

invoke

beforeInvocation

自定义的AuthorizeSecurityMetadataSource实现了FilterInvocationSecurityMetadataSourcegetAttributes()方法,可以根据url获取对应的角色列表

AuthorizeSecurityMetadataSource

自定义的AuthorizeAccessDecisionManager实现了AccessDecisionManager,实现了decide()方法来判断当前用户是否有此url的权限

AuthorizeAccessDecisionManager

框架默认的AccessDecisionManager通过投票决策的方式来授权

  • AffirmativeBased(spring security默认使用)

    只要有投通过(ACCESS_GRANTED=1)票,则直接判为通过。如果没有投通过票且反对(ACCESS_DENIED=-1)票在1个及其以上的,则直接判为不通过。

    AffirmativeBased
    vote

  • ConsensusBased(少数服从多数)

    通过的票数大于反对的票数则判为通过;通过的票数小于反对的票数则判为不通过;通过的票数和反对的票数相等,则可根据配置allowIfEqualGrantedDeniedDecisions(默认为true)进行判断是否通过。

  • UnanimousBased(反对票优先)

    无论多少投票者投了多少通过(ACCESS_GRANTED)票,只要有反对票(ACCESS_DENIED),那都判为不通过;如果没有反对票且有投票者投了通过票,那么就判为通过.

其他过滤器

ExceptionTranslationFilter

该过滤器主要用来捕获处理spring security抛出的异常,异常主要来源于FilterSecurityInterceptor

系列文章:《深入浅出Spring Security(一):三句话解释框架原理》

系列文章:《深入浅出Spring Security(二):FilterChainProxy的创建过程》

系列文章:《深入浅出Spring Security(三):FilterChainProxy的运行过程》

系列文章:《深入浅出Spring Security(四):WebSecurity与HttpSecurity》

本文链接:《深入浅出Spring Security(五):认证和授权的过程》