自定义认证逻辑
(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()
//......
}
}
这里配置分三步:
- 首先配置UserDetailsService 提供数据源;
- 提供一个AuthenticationProvider 实例并配置UserDetailsService;
- 最后重写authenticationManagerBean 方法,提供一个自己的ProviderManager 并用自定义的AuthenticationProvider 实例。
另外需要给验证码接口放行。.antMatchers(“/getVerifyCode”).permitAll()