Spring Security(九)— 添加登录验证码(自定义)

自定义认证逻辑

(1) 生成验证文本,并将文本存入 HttpSession 中;
(2) 根据验证码文本生成验证码图片,并通过 IO 流写出到前端

@RestController
public class LoginController {
    @GetMapping("/getVerifyCode")
    public void getVerifyCode(HttpServletResponse response, HttpSession sessoin) throws IOException {
        response.setContentType("image/png");
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        lineCaptcha.setGenerator(randomGenerator);
        // 重新生成code
        lineCaptcha.createCode();
        String text = lineCaptcha.getCode();
        sessoin.setAttribute("vc",text);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(lineCaptcha.getImage(),"png",out);
    }
}

接下来就是验证码的校验了,身份认证就是在AuthenticationProvider#authenticate 方法中完成的。所以我们可以在该方法执行前进行,需要配置如下类:

public class VcAuthenticationProvider extends DaoAuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException{
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String vc = request.getParameter("vc");
        String sessionVc = (String) request.getSession().getAttribute("vc");
        if (vc!=null && sessionVc!=null&&vc.equalsIgnoreCase(sessionVc)){
            return super.authenticate(authentication);
        }
        throw new AuthenticationServiceException("验证码输入错误!");
    }
}

这里重写了authenticate 方法,在authenticate 方法中,从RequestContextHolder 中获取当前请求,进而获取到验证码和存储在HttpSession 中的验证码文本进行比较,比较通过则继续执行父类的authenticate 方法,比较不通过,就抛出异常。

最后在SecurityConfig 中配置,AuthenticationManager,如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    MyUserDetailsService userDetailsService;
    
    @Bean
    public AuthenticationProvider vcAuthenticationProvider() {
        VcAuthenticationProvider provider = new VcAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        return provider;
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        ProviderManager manager = new ProviderManager(vcAuthenticationProvider());
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/getVerifyCode").permitAll()
                .anyRequest().authenticated()
                //......
	}
}

这里配置分三步:

  1. 首先配置UserDetailsService 提供数据源;
  2. 提供一个AuthenticationProvider 实例并配置UserDetailsService;
  3. 最后重写authenticationManagerBean 方法,提供一个自己的ProviderManager 并用自定义的AuthenticationProvider 实例。

另外需要给验证码接口放行。.antMatchers(“/getVerifyCode”).permitAll()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值