From be78725f27778e2de5c21d69ade449af4218b401 Mon Sep 17 00:00:00 2001 From: Tang Cheng Date: Tue, 2 Jul 2019 16:38:12 +0800 Subject: [PATCH] =?utf8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E9=AA=8C=E8=AF=81?= =?utf8?q?=E7=A0=81=20katptch?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../dlpay/framework/KaptchaConfig.java | 29 +++++ .../framework/filter/ValidateCodeFilter.java | 120 +++++++++--------- .../dlpay/framework/security/CodeUtil.java | 45 +++++++ .../controller/security_controller.kt | 24 +++- src/main/resources/templates/login.html | 2 +- src/main/resources/templates/ologin.html | 2 +- 7 files changed, 163 insertions(+), 60 deletions(-) create mode 100644 src/main/java/com/supwisdom/dlpay/framework/KaptchaConfig.java create mode 100644 src/main/java/com/supwisdom/dlpay/framework/security/CodeUtil.java diff --git a/build.gradle b/build.gradle index ae777ffa..790cd7dd 100644 --- a/build.gradle +++ b/build.gradle @@ -66,6 +66,7 @@ dependencies { implementation 'org.bitbucket.b_c:jose4j:0.6.3' implementation 'io.github.microutils:kotlin-logging:1.6.26' implementation 'org.slf4j:slf4j-parent:1.7.26' + implementation 'com.github.penggle:kaptcha:2.3.2' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5' implementation group: 'com.sun.jersey', name: 'jersey-client', version: '1.19' implementation group: 'javax.servlet', name: 'jstl', version: '1.2' diff --git a/src/main/java/com/supwisdom/dlpay/framework/KaptchaConfig.java b/src/main/java/com/supwisdom/dlpay/framework/KaptchaConfig.java new file mode 100644 index 00000000..c69dc38b --- /dev/null +++ b/src/main/java/com/supwisdom/dlpay/framework/KaptchaConfig.java @@ -0,0 +1,29 @@ +package com.supwisdom.dlpay.framework; + +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + +@Configuration +public class KaptchaConfig { + @Bean + public DefaultKaptcha getDefaultKaptcha(){ + DefaultKaptcha captchaProducer = new DefaultKaptcha(); + Properties properties = new Properties(); + properties.setProperty("kaptcha.border", "yes"); + properties.setProperty("kaptcha.border.color", "105,179,90"); + properties.setProperty("kaptcha.textproducer.font.color", "blue"); + properties.setProperty("kaptcha.image.width", "110"); + properties.setProperty("kaptcha.image.height", "40"); + properties.setProperty("kaptcha.textproducer.font.size", "30"); + properties.setProperty("kaptcha.session.key", "code"); + properties.setProperty("kaptcha.textproducer.char.length", "4"); + properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); + Config config = new Config(properties); + captchaProducer.setConfig(config); + return captchaProducer; + } +} diff --git a/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java b/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java index 7255657c..ac7a323b 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java +++ b/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java @@ -2,6 +2,7 @@ package com.supwisdom.dlpay.framework.filter; import com.supwisdom.dlpay.exception.ValidateCodeException; +import com.supwisdom.dlpay.framework.security.CodeUtil; import com.supwisdom.dlpay.framework.security.MyAuthenticationFailureHandler; import com.supwisdom.dlpay.framework.security.validate.ImageCodeUtil; import com.supwisdom.dlpay.framework.security.validate.VerifyCode; @@ -20,67 +21,72 @@ import java.io.IOException; @Component("validateCodeFilter") public class ValidateCodeFilter extends OncePerRequestFilter { - /** - * 校验失败处理器 - */ - @Autowired - private MyAuthenticationFailureHandler myAuthenticationFailureHandler; + /** + * 校验失败处理器 + */ + @Autowired + private MyAuthenticationFailureHandler myAuthenticationFailureHandler; - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - String context = request.getContextPath(); - if (context == null || "" == context.trim()) { - context = "/"; - } - if (request.getRequestURI().isEmpty()) { - filterChain.doFilter(request, response); - return; - } - String url = request.getRequestURI(); - if (!"/".equals(context)) { - url = url.replace(context, ""); - } - if (StringUtil.equals("/login/form", url) - && StringUtil.equalsIgnoreCase(request.getMethod(), "post")) { - try { - validate(request); - } catch (ValidateCodeException e) { - //response.setStatus(HttpStatus.OK.value()); - //response.setContentType("application/json;charset=UTF-8"); - //response.getWriter().write(objectMapper.writeValueAsString(JsonResult.error(400, e.getMessage()))); - //response.sendError(HttpStatus.UNAUTHORIZED.value(),e.getMessage()); - myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e); - return; - } - } - filterChain.doFilter(request, response); + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + String context = request.getContextPath(); + if (context == null || "" == context.trim()) { + context = "/"; } + if (request.getRequestURI().isEmpty()) { + filterChain.doFilter(request, response); + return; + } + String url = request.getRequestURI(); + if (!"/".equals(context)) { + url = url.replace(context, ""); + } + if (StringUtil.equals("/login/form", url) + && StringUtil.equalsIgnoreCase(request.getMethod(), "post")) { + try { + validate(request); + } catch (ValidateCodeException e) { + //response.setStatus(HttpStatus.OK.value()); + //response.setContentType("application/json;charset=UTF-8"); + //response.getWriter().write(objectMapper.writeValueAsString(JsonResult.error(400, e.getMessage()))); + //response.sendError(HttpStatus.UNAUTHORIZED.value(),e.getMessage()); + myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e); + return; + } + } + filterChain.doFilter(request, response); + } - private void validate(HttpServletRequest request) throws ValidateCodeException { - VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY); - String inputCode; - try { - inputCode = request.getParameter("imageCode"); - } catch (Exception e) { - throw new ValidateCodeException("获取验证码的值失败"); - } - if (StringUtil.isEmpty(inputCode)) { - throw new ValidateCodeException("验证码不能为空"); - } - if (null == imageCode) { - throw new ValidateCodeException("验证码不存在"); - } - if (imageCode.isExpired()) { - request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY); - throw new ValidateCodeException("验证码已过期"); - } - if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) { - throw new ValidateCodeException("验证码不匹配"); - } - request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY); + private void validate(HttpServletRequest request) throws ValidateCodeException { + if (!CodeUtil.checkVerifyCode(request)) { + throw new ValidateCodeException("验证码不匹配"); + } else { + request.getSession().removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); } +// VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY); +// String inputCode; +// try { +// inputCode = request.getParameter("imageCode"); +// } catch (Exception e) { +// throw new ValidateCodeException("获取验证码的值失败"); +// } +// if (StringUtil.isEmpty(inputCode)) { +// throw new ValidateCodeException("验证码不能为空"); +// } +// if (null == imageCode) { +// throw new ValidateCodeException("验证码不存在"); +// } +// if (imageCode.isExpired()) { +// request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY); +// throw new ValidateCodeException("验证码已过期"); +// } +// if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) { +// throw new ValidateCodeException("验证码不匹配"); +// } +// request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY); + } } diff --git a/src/main/java/com/supwisdom/dlpay/framework/security/CodeUtil.java b/src/main/java/com/supwisdom/dlpay/framework/security/CodeUtil.java new file mode 100644 index 00000000..ef3b475d --- /dev/null +++ b/src/main/java/com/supwisdom/dlpay/framework/security/CodeUtil.java @@ -0,0 +1,45 @@ +package com.supwisdom.dlpay.framework.security; + +import javax.servlet.http.HttpServletRequest; + +public class CodeUtil { + /** + * 将获取到的前端参数转为string类型 + * + * @param request + * @param key + * @return + */ + public static String getString(HttpServletRequest request, String key) { + try { + String result = request.getParameter(key); + if (result != null) { + result = result.trim(); + } + if ("".equals(result)) { + result = null; + } + return result; + } catch (Exception e) { + return null; + } + } + + /** + * 验证码校验 + * + * @param request + * @return + */ + public static boolean checkVerifyCode(HttpServletRequest request) { + //获取生成的验证码 + String verifyCodeExpected = (String) request.getSession() + .getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); + //获取用户输入的验证码 + String verifyCodeActual = CodeUtil.getString(request, "verifyCodeActual"); + if (verifyCodeActual == null || !verifyCodeActual.equals(verifyCodeExpected)) { + return false; + } + return true; + } +} diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt index 0bb3345c..81f099de 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt @@ -1,5 +1,6 @@ package com.supwisdom.dlpay.framework.controller +import com.google.code.kaptcha.Producer import com.supwisdom.dlpay.exception.TransactionCheckException import com.supwisdom.dlpay.framework.ResponseBodyBuilder import com.supwisdom.dlpay.framework.core.JwtConfig @@ -33,7 +34,9 @@ import org.springframework.stereotype.Controller import org.springframework.ui.Model import org.springframework.web.bind.annotation.* import org.springframework.web.context.request.ServletWebRequest +import java.awt.image.BufferedImage import java.io.IOException +import java.lang.Exception import java.security.Principal import java.util.* import javax.imageio.ImageIO @@ -184,11 +187,30 @@ class ApiAuthController { @RestController class ValidateCodeController { + @Autowired + private lateinit var captchaProducer: Producer + @GetMapping("/code/image") fun createCode(request: HttpServletRequest, response: HttpServletResponse) { val imageCode = VerifyCode(60) HttpSessionSessionStrategy().setAttribute(ServletWebRequest(request), ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY, imageCode) - ImageIO.write(imageCode.image, "JPEG", response.outputStream) + val session = request.session + response.setDateHeader("Expires", 0) + response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate") + response.addHeader("Cache-Control", "post-check=0, pre-check=0") + response.setHeader("Pragma", "no-cache") + response.contentType = "image/jpeg" + //生成验证码 + val capText = captchaProducer.createText() + session.setAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY, capText) + //向客户端写出 + val bi = captchaProducer.createImage(capText); + ImageIO.write(bi, "JPEG", response.outputStream) + try { + response.outputStream.flush() + } catch (ex: Exception) { + response.outputStream.close() + } } } diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index d5d6c7b0..a87ae827 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -45,7 +45,7 @@
-
diff --git a/src/main/resources/templates/ologin.html b/src/main/resources/templates/ologin.html index 8f9362eb..ac043c3b 100644 --- a/src/main/resources/templates/ologin.html +++ b/src/main/resources/templates/ologin.html @@ -42,7 +42,7 @@
-
-- 2.17.1