堆栈里的悄悄话——智能指针
这个问题,网上找了好多,结果代码都不全,找了好多,要不是就自动注入的类注入不了,编译报错,要不异常捕获不了浪费好多时间,就觉得,框架不熟就不能随便用,全是坑,气死我了,最后改了两天.终于弄好啦;
问题主要是:
- 返回的验证码不知道在SpringSecurity的哪里和存在Session里的比较.
- 比较之后应该怎么处理,
- 其次是捕获验证码错误异常的处理,
这个问题比较多,网上大都是直接注入一个AuthenticationFailureHandler,我就不明白这个咋注进去的,我这个一写就报错,注入不进去,后来就想自己new一个哇,就OK了
new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); RespBean respBean = RespBean.error("验证码错误!"); out.write(new ObjectMapper().writeValueAsString(respBean)); out.flush(); out.close(); } }.onAuthenticationFailure(request, response, e); return;
流程
-
请求登录页,将验证码结果存到基于Servlet的session里,以JSON格式返回验证码,
-
之后前端发送登录请求,SpringSecurity中处理,自定义一个filter让它继承自OncePerRequestFilter,然后重写doFilterInternal方法,在这个方法中实现验证码的功能,如果验证码错误就抛出一个继承自AuthenticationException的验证吗错误的异常消息写入到响应消息中.
-
之后返回异常信息
下面以这个顺序书写代码:
依赖大家照着import导一下吧,记得有这两个,验证码需要一个依赖,之后还使用了一个工具包
<!--图片验证--> <dependency> <groupId>com.github.whvcse</groupId> <artifactId>easy-captcha</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency>
前端使用Vue+ElementUI
<div class="login-code"> <img :src="codeUrl" @click="getCode"> </div>
后端代码:
数组去重
获取验证码,将结果放到session里
package com.liruilong.hros.controller; import com.liruilong.hros.model.RespBean; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.wf.captcha.ArithmeticCaptcha; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; /** * @Description : * @Author: Liruilong * @Date: 2019/12/19 19:58 */ @RestController public class LoginController { @GetMapping(value = "/auth/code") public Map getCode(HttpServletRequest request,HttpServletResponse response){ // 算术类型 https://gitee.com/whvse/EasyCaptcha ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36); // 几位数运算,默认是两位 captcha.setLen(2); // 获取运算的结果 String result = captcha.text(); System.err.println("生成的验证码:"+result); // 保存 // 验证码信息 Map<String,Object> imgResult = new HashMap<String,Object>(2){{ put("img", captcha.toBase64()); }}; request.getSession().setAttribute("yanzhengma",result); return imgResult; } }
security配置.
在之前的基础上加filter的基础上加了
http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class)
/** * @Author Liruilong * @Description 放行的请求路径 * @Date 19:25 2020/2/7 * @Param [web] * @return void **/ @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/login","/css/**","/js/**", "/index.html", "/img/**", "/fonts/**","/favicon.ico","/auth/code"); } @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class) .authorizeRequests() //.anyRequest().authenticated() ........... }
定义一个VerifyCodeFilter 过滤器
package com.liruilong.hros.filter; import com.fasterxml.jackson.databind.ObjectMapper; import com.liruilong.hros.Exception.ValidateCodeException; import com.liruilong.hros.model.RespBean; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Bean; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @Description : * @Author: Liruilong * @Date: 2020/2/7 19:39 */ @Component public class VerifyCodeFilter extends OncePerRequestFilter { @Bean public VerifyCodeFilter getVerifyCodeFilter() { return new VerifyCodeFilter(); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, ValidateCodeException { if (StringUtils.equals("/doLogin", request.getRequestURI()) && StringUtils.equalsIgnoreCase(request.getMethod(), "post")) { // 1. 进行验证码的校验 String requestCaptcha = request.getParameter("code"); String code = (String) request.getSession().getAttribute("yanzhengma"); logger.info("开始校验验证码,生成的验证码为:" + code + " ,输入的验证码为:" + requestCaptcha); try { if (StringUtils.isBlank(requestCaptcha)) { throw new ValidateCodeException("验证码不能为空!"); } if (requestCaptcha == null) { throw new ValidateCodeException("验证码不存在"); } if (!StringUtils.equals(code, requestCaptcha)) { throw new ValidateCodeException("验证码不匹配"); } } catch (AuthenticationException e) { // 2. 捕获步骤1中校验出现异常,交给失败处理类进行进行处理 new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); RespBean respBean = RespBean.error("验证码错误!"); out.write(new ObjectMapper().writeValueAsString(respBean)); out.flush(); out.close(); } }.onAuthenticationFailure(request, response, e); return; } filterChain.doFilter(request, response); } filterChain.doFilter(request, response); } }
之后就可以啦
感觉主要是捕获验证码错误异常的处理,
这个问题比较多,网上大都是直接注入一个AuthenticationFailureHandler,我就不明白这个咋注进去的,我这个一写就报错,注入不进去,后来就想自己new一个哇,
new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); RespBean respBean = RespBean.error("验证码错误!"); out.write(new ObjectMapper().writeValueAsString(respBean)); out.flush(); out.close(); } }.onAuthenticationFailure(request, response, e); return;
mac如何用quick look预览多个文件或者图片
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END