【Spring Security安全框架 入门及基于微服务单点登录认证】

前言

Spring Security是一个当前流行的安全框架,它不仅实现了访问资源(crud)权限的控制,还可以基于它可以实现单点登陆认证业务.
本文主要介绍Spring Security的概念,认证及权限控制原理,以及单点登录的实现.

一、Spring Security的概念

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架(简单说是对访问权限进行控制的一个框架)。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

二、Spring Security的实现原理

Spring Security对Web安全性的支持大量地依赖于Servlet过滤器。通过这些过滤器拦截进入请求,判断是否已经登录认证且具访问对应请求的权限。
Spring Security 执行流程图:
目前的登陆操作,也就是用户的认证操作,其实现主要基于Spring Security框架,其认证简易流程如下:
要完成访问控制,Spring Security至少需要四个拦截器(调度器、认证管理器、权限资源关联器、访问决策器)进行配合完成:
SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。

1.过滤器链的各个进行说明:

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

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

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

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

  5. LogoutFilter:用于处理退出登录。

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

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

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

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

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

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

  12. SessionManagementFilter:管理 session 的过滤器

  13. ExceptionTranslationFilter:处理 AccessDeniedException 和 AuthenticationException 异常。

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

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

2.简易流程概述:

  1. 客户端发起一个请求,进入 Security 过滤器链。
  2. 当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到 logoutSuccessHandler 登出成功处理,如果登出失败则由 ExceptionTranslationFilter ;如果不是登出路径则直接进入下一个过滤器。
  3. 当到 UsernamePasswordAuthenticationFilter*( 该对象是 Authentication 接口的实现类,该类有两个构造器,一个用于封装前端请求传入的未认证的用户信息,一个用于封装认证成功后的用户信息) 的时候判断是否为登录路径,如果是,则进入该过滤器进行登录操作,如果登录失败则到 AuthenticationFailureHandler 登录失败处理器处理,如果登录成功则到 AuthenticationSuccessHandler 登录成功处理器处理,如果不是登录请求则不进入该过滤器。
  4. 当到 FilterSecurityInterceptor 的时候会拿到 uri ,根据 uri 去找对应的鉴权管理器,鉴权管理器做鉴权工作,鉴权成功则到 Controller 层否则到 AccessDeniedHandler 鉴权失败处理器处理。

3. 具体认证流程

在这里插入图片描述

  1. 用户发起登录请求,通过Security 过滤器链,到达UsernamePasswordAuthenticationFilter 过滤器.

  2. UsernamePasswordAuthenticationFilter过滤器的 attemptAuthentication() 方法将未认证的 Authentication 对象传入ProviderManager 类的 authenticate() 方法进行身份认证。ProviderManager 是 AuthenticationManager 接口的实现类,该接口是认证相关的核心接口,也是认证的入口。在实际开发中,我们可能有多种不同的认证方式,例如:用户名+ 密码、邮箱+密码、手机号+验证码等,而这些认证方式的入口始终只有一个,那就是 AuthenticationManager。

  3. AuthenticationManager接口的常用实现类 ProviderManager 内部会维护一个 List 列表,存放多种认证方式,实际上这是委托者模式 (Delegate)的应用。每种认证方式对应着一个 AuthenticationProvider.

  4. AuthenticationManager 根据认证方式的不同(根据传入的 Authentication 类型判断)委托对应的 AuthenticationProvider(实际上使用的是他的实现类DaoAuthenticationProvider) 进行用户认证。认证时需要UserDetailsService接口的实现类来传递用户信息.

  5. 自定义类XxUserDetailService实现UserDetailsService接口和其loadUserByUsername方法,这个方法根据用户输入的用户名,从数据库里面(常用微服务远程访问的方式)获取该用户的所有权限信息(统称用户信息)。MyUserDetailService拿到用户信息后,传给AuthenticationProvider(实际上使用的是他的实现类DaoAuthenticationProvider) 对比用户的密码(即验证用户),如果通过了,那么相当于通过了AuthenticationProcessingFilter拦截器,也就是登录验证通过。

三 、springsecurity使用redis实现单点登录

  1. 创建web安全配置类
    这个类是单体项目中经常使用到的类,但现在登录走的是Oauth2的流程,因此它只需要负责创建一些对象以及配置一下放行和认证规则就行,放行loginController下的所有方法是因为登录不需要被拦截。
/**
 * Security 配置类
 */
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
   


    // 初始化密码编码器,用BCryptPasswordEncoder加密密码
    @Bean
    public PasswordEncoder passwordEncoder() {
   
        return new BCryptPasswordEncoder();
    }

    // 初始化认证管理对象,密码模式需要
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
   
        return super.authenticationManagerBean();
    }

    // 放行和认证规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
        http.csrf().disable()
                .authorizeRequests()
                // 放行的请求
                .antMatchers("/loginController/**").permitAll()
                .and()
                .authorizeRequests()
                // 其他请求必须认证才能访问
                .anyRequest().authenticated
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值