IT技术篇我爱编程程序员

Spring Security 详解

2017-12-14  本文已影响445人  聪明的奇瑞

Spring Security 是一个基于 Spring AOP 和 Servlet 过滤器的安全框架,它提供了安全性方面的解决方案,同时在Web请求和方法级处理身份确认和授权

Spring Boot 添加 Spring Security

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Spring Security 模块

认证流程

  1. 用户使用用户名和密码登录
  2. 用户名密码被过滤器(默认为 UsernamePasswordAuthenticationFilter)获取到,封装成 Authentication
  3. token(Authentication实现类)传递给 AuthenticationManager 进行认证
  4. AuthenticationManager 认证成功后返回一个封装了用户权限信息的 Authentication 对象
  5. 通过调用 SecurityContextHolder.getContext().setAuthentication(...) 将 Authentication 对象赋给当前的 SecurityContext

    默认执行顺序:

    UsernamePasswordAuthenticationFilter :

    1. 用户通过url:/login 登录,该过滤器接收表单用户名密码
    2. 判断用户名密码是否为空
    3. 生成 UsernamePasswordAuthenticationToken
    4. 将 Authentiction 传给 AuthenticationManager接口的 authenticate 方法进行认证处理
    5. AuthenticationManager 默认是实现类为 ProviderManager ,ProviderManager 委托给 AuthenticationProvider 进行处理
    6. UsernamePasswordAuthenticationFilter 继承了 AbstractAuthenticationProcessingFilter 抽象类,AbstractAuthenticationProcessingFilter 在 successfulAuthentication 方法中对登录成功进行了处理,通过 SecurityContextHolder.getContext().setAuthentication() 方法将 Authentication 认证信息对象绑定到 SecurityContext
    7. 下次请求时,在过滤器链头的 SecurityContextPersistenceFilter 会从 Session 中取出用户信息并生成 Authentication(默认为 UsernamePasswordAuthenticationToken),并通过 SecurityContextHolder.getContext().setAuthentication() 方法将 Authentication 认证信息对象绑定到 SecurityContext
    8. 需要权限才能访问的请求会从 SecurityContext 中获取用户的权限进行验证

    DaoAuthenticationProvider (实现了 AuthenticationProvider):

    1. 通过 UserDetailsService 获取 UserDetails
    2. 将 UserDetails 和 UsernamePasswordAuthentionToken 进行认证匹配用户名密码是否正确
    3. 若正确则通过 UserDetails 中用户的权限、用户名等信息生成一个新的 Authentication 认证对象并返回

相关类

WebSecurityConfigurerAdapter

SecurityContextHolder

AuthenticationManagerBuilder

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.inMemoryAuthentication()
            .withUser("user").password("123").roles("USER").and()
            .withUser("admin").password("456").roles("USER","ADMIN");
}
@Autowired
private DataSource dataSource;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication()
            .dataSource(dataSource)
            .withDefaultSchema()
            .withUser("linyuan").password("123").roles("USER").and()
            .withUser("linyuan2").password("456").roles("ADMIN");
}

UserDetailsService

UserDetails

Authentication

GrantedAuthority

AuthenticationManager

AuthenticationProvide

AuthorityUtils

AbstractAuthenticationProcessingFilter

UserDetails

HttpSecurity

注解与Spring EL

@PreAuthorize("hasRole('ROLE_ADMIN')")
public void addUser(User user){
    //如果具有权限 ROLE_ADMIN 访问该方法
    ....
}
//returnObject可以获取返回对象user,判断user属性username是否和访问该方法的用户对象的用户名一样。不一样则抛出异常。
@PostAuthorize("returnObject.user.username==principal.username")
public User getUser(int userId){
   //允许进入
...
    return user;    
}
//将结果过滤,即选出性别为男的用户
@PostFilter("returnObject.user.sex=='男' ")
public List<User> getUserList(){
    //允许进入
    ...
    return user;    
}

Spring EL 表达式:

表达式 描述
hasRole ([role]) 当前用户是否拥有指定角色
hasAnyRole([role1,role2]) 多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true
hasAuthority ([auth]) 等同于hasRole
hasAnyAuthority([auth1,auth2]) 等同于 hasAnyRole
Principle 代表当前用户的 principle对象
authentication 直接从 Security context获取的当前 Authentication对象
permitAll 总是返回true,表示允许所有的访问
denyAll 总是返回false,表示拒绝所有的访问访问
isAnonymous() 当前用户是否是一个匿名用户
isRememberMe 表示当前用户是否是通过remember - me自动登录的
isAuthenticated() 表示当前用户是否已经登录认证成功了
isFullAuthenticated() 如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true

密码加密(PassWordEncoder)

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

过滤器链

SecurityContextPersistenceFilter

WebAsyncManagerIntegrationFilter

HanderWriterFilter

CsrfFilter

LogoutFilter

UsernamePasswordAuthenticationFilter

DefaultLoginPageGeneratingFilter

BasicAuthenticationFilter

RequestCacheAwareFilter

SecurityContextHolderAwareRequestFilter

AnonymousAuthenticationFIlter

SessionManagementFilter

ExceptionTranslationFilter

上一篇 下一篇

猜你喜欢

热点阅读