我们接着上一章 (二)Spring Security自定义登录成功或失败处理器,进行开发
一:首先声明一个验证码异常
/**
* 声明一个验证码异常,用于抛出特定的验证码异常
*/
public class VerifyCodeException extends AuthenticationException {
public VerifyCodeException(String msg) {
super(msg);
}
}
二:创建一个验证码过滤器
@Component
public class VerifyCodeFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(VerifyCodeFilter.class);
@Autowired
private LoginFailureHandler loginFailureHandler;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(request.getRequestURI().equals("/login")&&request.getMethod().equalsIgnoreCase("post")){
try {
validate(request);
} catch (VerifyCodeException e) {
loginFailureHandler.onAuthenticationFailure(request,response,e);
return;
}
}
// 3. 校验通过,就放行
filterChain.doFilter(request, response);
}
/* 验证保存在session的验证码和表单提交的验证码是否一致 */
private void validate(HttpServletRequest request) throws ServletRequestBindingException {
String captcha = ServletRequestUtils.getStringParameter(request, "captcha");
String code = (String) request.getSession().getAttribute(request.getParameter("uuid"));
log.info("获取提交的code",captcha);
log.info("获取保存的code",code);
if(!code.equalsIgnoreCase(captcha)){
throw new VerifyCodeException("验证码不正确!");
}
request.getSession().removeAttribute(request.getParameter("uuid"));
}
}
三:在WebSecurityConfig中添加过滤器
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() /* 需要授权的请求 */
.antMatchers("/login","/home").permitAll() /* 过滤不需要认证的路径 */
.anyRequest().authenticated() /* 对任何一个请求,都需要认证 */
.and() /* 完成上一个配置,进行下一步配置 */
//.httpBasic();
.formLogin() /* 配置表单登录 */
.loginPage("/login") /* 设置登录页面 */
.successHandler(successHandler) /* 设置成功处理器 */
.failureHandler(failureHandler) /* 设置失败处理器*/
.and()
.logout() /* 登出 */
.logoutSuccessUrl("/home"); /* 设置退出页面 */
/* 添加验证码过滤器 */
http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
}
四:controller输出验证码到页面
@RestController
public class MainController {
@GetMapping(value = "/123")
public Object login(){
return "hello world";
}
@GetMapping("/getCode")
public Object getCode(HttpServletRequest request) {
/* 生成验证码字符串 */
String verifyCode = VerifyCodeUtil.generateVerifyCode(4);
String uuid = UUIDUtil.GeneratorUUIDOfSimple();
HttpSession session = request.getSession();
session.setAttribute(uuid,verifyCode);
int w = 111,h = 36;
try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
VerifyCodeUtil.outputImage(w, h, stream, verifyCode);
return new BaseResult(ReturnCode.SUCCESS.getCode(), ReturnCode.SUCCESS.getMessage(),new ImgVO("data:image/gif;base64,"+ Base64Utils.encodeToString(stream.toByteArray()),uuid));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
五:前端接收
示例: