spring Security工作原理总括

术,spring Security就是采用的Filter进行拦截。

当初始化spring Security时,会创建一个名为SpringSecurityFilterChain的Servlet过滤器,

类型为org.springframework.security.web.FilterChainProxy,他实现了javax.servlet.Filter,因此外部的请求会进过此类。

spring Security过滤器链的结果大致为:

  FilterChainProxy  ----->FIlter1----->FIlter2----->FIlter...----->system resource

  其中认证的FIlter调用的是AuthenticationManger干活

  其中授权的FIlter调用的是accessDesionManager干活

 

首先请求过来后传入到第一个Filter,为SecurityContextPersistenceFilter,接着会到判断用户身份的Filter,为

UsernamePasswordAuthencationFIlter,来校验用户身份,当然这会委托AuthenticationManager来校验。

然后再传入其他Filter进行处理。

 

SecurityContextPersistenceFIlter是整个过滤器链的第一个Filter(入出口)主要做一些上下文的初始化工作,

授权的Filter由FilterSecurityInterceptor来做,当然这是委托AccessDesionManager来做。

 

如果抛出异常,则由ExceptionTransationFilter来进行处理。

 

================================================================================

 

认证流程(大致)

首先用户提交用户名密码后,将封装用户密码的请求会发送到UsernamePasswordAuthenticationFilter中,然后

调用authenticate()交给认证器AuthenticationManager来进行处理,AuthenticationManager也不是最终干活的,

他会调用authenticate()方法交给DaoAutnenticationProvider来最终干活,DaoAutnenticationProvider通过调用

loadUserByUsername()方法访问UserDetailsServer服务获取用户信息,返回的UserDetails对象,包含了数据库中的用户信息。

DaoAutnenticationProvider拿到了用户信息后,会调用以前讲过的PasswordEncoder对比UserDetails中的密码是否一致,

认证通过会将用户信息填充到Authentication中并且返回到UsernamePasswordAuthenticationFilter,

UsernamePasswordAuthenticationFilter通过SecurityContextHolder.getcontext().setAuthentication()将Authentication

的认证信息保存到上下文中。认证就结束了。其中的UsernamePasswordAuthenticationFilter,

DaoAutnenticationProvider等组件都是可以自定义的,但是一般不需要改这些类。但是有一点可以改UserDetailsServer服务,

通过查数据库等方式来获取用户信息。

创建一个service包,在下面作如下

@service
public class SpringDataUserDetailService implements UserDetailsService{
  @Override
  public UserDetails loadUserByUsername(String s)throws UsernameNotFoundException{
    //链接数据库 查询数据库
    //模拟
    UserDteails userDteails= User.withUsername("xxx").password("xxx").authorties("xxx").build();
    return userDteails;
  }
}

然后将原来SecurityConfig里面的UserDetailsService的配置Bean去掉。就可以执行这个自定义的方法了。

另外,SecurityConfig中的PasswordEncoder需要修改,建议采用BCriptPasswordEncoder来进行编码

好处是,每次编码的字符串不一样,安全性高,并且都可以验证通过。

================================================================================

 

授权流程(大致)

 

 认证后的用户访问受保护的资源会进入到FilterSecurityInterceptor过滤器中,FilterSecurityInterceptor通过

SecurityMetaDataSource类的getAttribute()获取资源权限,并且返回权限集合Collection<ConfigAttribute>到

FilterSecurityInterceptor,FilterSecurityInterceptor再通过AccessDesionManage的deside()方法进行授权决策

判断,通过决策则允许访问资源,请求放行。