【SpringSecurity】Security工作流程的理解

一、过滤器链

security底层就是由多个过滤器组成的过滤器链:

WebAsyncManagerIntegrationFilter:将 Security 上下文与 Spring Web 中用于处理异步请求映射的 WebAsyncManager 进行集成。

SecurityContextPersistenceFilter:在每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中,然后在该次请求处s理完成之后,将 SecurityContextHolder 中关于这次请求的信息存储到本地,然后将 SecurityContextHolder 中的信息清除,例如在session中维护一个用户的安全信息就是这个过滤器处理的。

HeaderWriterFilter:用于将头信息加入响应中。

CsrfFilter:用于处理跨站请求伪造。

LogoutFilter:用于处理退出登录。

UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。默认情况下处理来自 /login 的请求。从表单中获取用户名和密码时,默认使用的表单 name 值为 username 和 password,这两个值可以通过设置这个过滤器的usernameParameter 和 passwordParameter 两个参数的值进行修改。

DefaultLoginPageGeneratingFilter:如果没有配置登录页面,那系统初始化时就会配置这个过滤器,并且用于在需要进行登录时生成一个登录表单页面。

BasicAuthenticationFilter:检测和处理 http basic 认证。

RequestCacheAwareFilter:用来处理请求的缓存。

SecurityContextHolderAwareRequestFilter:主要是包装请求对象request。

AnonymousAuthenticationFilter:检测 SecurityContextHolder 中是否存在 Authentication 对象,如果不存在为其提供一个匿名 Authentication。

SessionManagementFilter:管理 session 的过滤器

ExceptionTranslationFilter:处理 AccessDeniedException 和 AuthenticationException 异常。

FilterSecurityInterceptor:可以看做过滤器链的出口。

RememberMeAuthenticationFilter:当用户没有登录而直接访问资源时, 从 cookie 里找出用户的信息, 如果 Spring Security 能够识别出用户提供的remember me cookie, 用户将不必填写用户名和密码, 而是直接登录进入系统,该过滤器默认不开启。
 

二、放行资源的方式

 第一种:放行静态资源

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/css/**", "/js/**", "/index.html", "/img/**", "/fonts/**", "/favicon.ico", "/verifyCode");
}

第二种:放行需要使用到用户信息的接口

http.authorizeRequests()
        .antMatchers("/hello").permitAll()
        .anyRequest().authenticated()

        两种放行资源的方式是有区别的!!!第一种是直接放行,资源不会经过security的过滤器链,也就是该资源和security无关了;第二种也是放行,但会经过security的过滤器链,这里踩过一个坑,就是在需要获取到用户信息的时候,但又希望这个接口是不需要权限的,比如自己实现安全退出,需要去使acess_token和refresh_token失效,然后清空session,如果我们走第一种放行,那么就不会经过security上下文持久化(Persistence)的过滤器,SecurityContext里就没有用户信息。

        这里也就又引出一个问题,那么security是怎么存储用户信息的?

       我们获取用户信息是通过SecurityContextHolder,SecurityContextHolder的数据,实际是存在ThreadLocal中的,ThreadLocal的特点是,存储在它里面的数据,哪个线程存的,哪个线程才能拿。当用户登录后(thread1),SecurityContextHolder保存了用户的信息,然后该次请求完毕后,为了保证下一次请求(线程)能拿到用户的数据,此时security把SecurityContextHolder的数据放到session里面,这样下一次请求进来经过SecurityContextPersistence就可以把session中的用户信息加载到SecurityContextHolder中,这样本次请求需要用到用户信息的地方,就可以直接从SecurityContextHolder里拿了。

三、过滤器的工作流程

1.Security的过滤器链UsernamePasswordAuthenticationFilter拦截到用户请求后,将其封装到请求Authentication中,这里的实现类是UsernamePasswordAuthenticationToken,把用户输入的账号和密码传进去。

2.然后过滤器把封装好的Authentication交给AuthenticationManager,认证管理器调用authenticate方法,之后根据用户名查询数据库,这里我们需要实现UserDetailsService,实现loadByUsername方法,根据这个方法名字我们就知道,我们是通过用户名去数据库查询是否有这个用户,然后把查询出来的用户交给Security去验证matches密码是否正确,在loadByUsername方法中需要返回security的user,也就是实现userdetails接口的user,里面有四个boolean类型的参数,就是看用户有没有凭证或者是否被禁用,还有getAccount和getPassword和getAuthorities可以获取用户的信息。

3.认证成功后,AuthenticationManager身份管理器返回一个被填充信息的(权限、用户名等)Authentication实例。

4.SecurityContextHolder安全上下文容器把认证成功的authentication实例set到SecurityContext里面。可以看到AuthenticationManager接口是认证相关的核心接口,也是发起认证的出发点,他的实现类是ProvideManager。而SpringSecurity支持多种认证方式,因此ProviderManager维护着一个List集合,存放多种认证方式,最终实际的认证工作是由AuthenticationProvider完成的。web表单对应的Provider是DaoAuthenticationProvider,里面又维护了一个UserDetailsService负责UserDetails的获取,最终由AuthenticationProvider把UserDetails填充到Authentication。

SpringBoot整合Spring Security OAuth2.0认证授权_Qblue666的博客-CSDN博客_springboot整合oauth2.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值