Spring Boot+Spring Security项目开发(二):Spring Security、实现图形验证码功能、实现"记住我"功能

说在前面

博主最近会有很多项目跟大家一起分享,做完后会上传github上的,希望读友们能给博主提提意见哈哈

这个项目是第三方登录和安全方面的,关于后台与app和网站的登录连接操作的实战项目


Spring Security


使用Spring Security开发基于表单的认证

核心功能:
  • 认证(你是谁)
  • 授权(你能干什么)
  • 攻击防护(防止伪造身份)

SpringSecurity基本原理

第一步:请求提交
第二步:过滤器链去认证
第三步:到达FilterSecurityInterceptor进行最后一层验证(这里可以作VIP和普通用户的认证,如果这里认证失败,则抛出异常,传递到ExecptionTranslationFilter进行解析)
第四步:ExecptionTranslationFilter解析出认证失败的地方,传回过滤器链中对应的Filter进行认证处理
第五步:认证成功的话调用服务端的REST API


自定义用户认证逻辑

处理用户信息获取逻辑
处理用户校验逻辑
  • UserDetailsService
处理密码加密解密
  • PasswordEncoder
  • 同样的密码每次加密出来的结果都是不一样的
  • 处理流程:注册时进行passwordEncoder.encode(密码)加密->存入数据库->登录时认证->取出数据库里的密码(加密过的)->比较,加密串中含随机生成的盐,判断的时候通过随机生成的盐反推回去

个性化用户认证流程

自定义登录页面
  • http.formLogin().loginPage(“/tihom-signIn.html”)
  • 在application中做配置跳转页面,如果没有配置则跳转到默认的登录页面
  • 定义一个系统配置项SecurityProperties,它里面包含BrowserProperties这个配置项,与browser有关的属性都会配置在这个BrowserProperties中
  • 在SecurityProperties上配置@ConfigurationProperties(prefix = “tihom.security”),意思是这个类会读取整个系统中以tihom.security开头的配置
  • 定义一个SecurityCoreConfig核心配置类,在它上面配置@Configuration和@EnableConfigurationProperties(SecurityProperties.class),配置配置读取器,让这些类生效

这里写图片描述
这里写图片描述

自定义登录成功处理

  • 实现接口AuthenticationSuccessHandler,定义为组件
  • 在BrowserSecurityConfig中配置successHandler()处理器
  • 每日签到
  • 积分记录

自定义登录失败处理

  • 同理

认证流程源码级详解

认证处理流程说明
  • 1.进入UsernamePasswordAuthenticationFilter
    这里写图片描述
    这里写图片描述
    这里写图片描述
  • 2.AuthenticationManager,这是管理AuthenticationProvider的,拿到上一步传入的token后,遍历AuthenticationProvider去找到合适的认证逻辑,挨个询问是否支持这个token所需求的登录方式
  • 3.进入xxxAuthenticationProvider(继承AbstractUserDetailsAuthenticationProvider)去处理认证->retrieveUser()方法->UserDetailsService->UserDetails(数据库中拿出来的用户信息)->preAuthenticationChecks(预检查),检查用户是否锁定、检查用户是否过期->additionalAuthenticationChecks(附加的检查),如校验密码是否匹配等->postAuthenticationChecks(后检查)
  • 4.createSuccessAuthentication->new UsernamePasswordAuthenticationToken(三个参数的构造函数,因为此时已经认证了,setAuthenticated(true))

这里写图片描述

认证结果如何在多个请求之间共享

  • SecurityContextPersistenceFilter:在整个过滤器链的最前面,请求先经过它,检查session里面是否有SecurityContext,有就把SecurityContext拿出来放到ThreadLocal线程里,没有就空的过去了;当整个请求响应回来之后再次经过的时候,它检查线程,如果线程里面有SecurityContext就拿出来放到session里面去.这样不同的请求就可以同一个session里面拿到相同的用户认证信息,拿到以后放到线程里面,因为整个的请求和响应的过程都在一个线程里完成的,所以在线程的其他位置随时可以通过SecurityContextHolder来拿到用户信息

这里写图片描述

获取认证用户信息

  • 在UserController中
@GetMapping("/me")
    public Object getCurrentUser(@AuthenticationPrincipal UserDetails user/* Authentication authentication*/){
//        return SecurityContextHolder.getContext().getAuthentication();
        //Spring会自动去SecurityContext对象里去找
//        return authentication;
        return user;
    }

实现图形验证码功能

开发生成图形验证码接口
  • 根据随机数生成图片
  • 将随机数存到session中
  • 将生成的图片写到接口的响应中
在认证流程中加入图形验证码校验
重构图形验证码接口

这里写图片描述

1.验证码基本参数可配置

应用级配置
* 将验证码的大小等基本参数,定义一个验证码图片配置类和一个验证配置类,前者继承于后者
* 在SecutiryProperties中配置验证配置类
* 这样在application.properties中就可以作全局配置了
请求级的配置
* 在控制器中配置Generator的实现

2.验证码拦截的接口可配置

多个请求都需要验证图形验证码

3.验证码的生成逻辑可配置

把验证码生成的逻辑转移到一个ImageCodeGenerator发生器
在ValidateCodeBeanConfig中配置ValidateCodeGenerator

最后基本逻辑是:ValidateCodeBeanConfig配置类->ValidateCodeGenerator接口->ImageCodeGenerator接口实现类(含SecurityProperties)->ValidateCodeController控制器(调用ValidateCodeGenerator接口,但是使用的是imageCodeGenerator)->生成验证码


实现”记住我”功能

记住我功能的基本原理

这里写图片描述

记住我功能的具体实现

在BrowserProperties中配置过期时间
浏览器配置类中添加persistentTokenRepository
在configure中配置

.rememberMe()
    .tokenRepository(persistentTokenRepository())
    .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
    .userDetailsService(userDetailsService)

记住我功能SpringSecurity源码解析

进入UsernamePasswordAuthenticationFilter->进入AbstractAuthenticationProcessingFilter(调用rememberMeServices服务)->onLoginSuccess(用tokenRepository创建新的token,添加到cookie中)

->到这里登录完成

下次登录
进入RememberMeAuthenticationFilter(调用rememberMeServices的autoLogin方法)->从请求的cookie中拿到token和series,然后根据series值去数据库里拿token和用户信息->作判断->UserDetailsService调用户信息->SecurityContextHolder.getContext().setAuthentication(rememberMeAuth)把用户信息放入session里

猜你喜欢

转载自blog.csdn.net/tryandfight/article/details/80461315
今日推荐