diff --git a/tamguo-oms/pom.xml b/tamguo-oms/pom.xml index 46e09ef..0e42ddf 100644 --- a/tamguo-oms/pom.xml +++ b/tamguo-oms/pom.xml @@ -94,17 +94,6 @@ commons-io commons-io - - com.github.penggle - kaptcha - 2.3.2 - - - javax.servlet-api - javax.servlet - - - com.alibaba druid @@ -138,6 +127,12 @@ thymeleaf-extras-shiro 1.2.1 + + + com.bladejava + blade-patchca + 1.0.5 + diff --git a/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java b/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java index f14b0d7..30ee016 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java @@ -1,17 +1,12 @@ package com.tamguo.config; -import java.util.Properties; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import com.google.code.kaptcha.impl.DefaultKaptcha; -import com.google.code.kaptcha.util.Config; import com.tamguo.modules.sys.interceptor.SettingsInterceptor; @Configuration @@ -32,21 +27,4 @@ public class WebConfig implements WebMvcConfigurer { registry.addResourceHandler("/files/**").addResourceLocations("file:"+fileStoragePath); } - @Bean(name="producer") - public DefaultKaptcha getKaptchaBean(){ - DefaultKaptcha defaultKaptcha=new DefaultKaptcha(); - Properties properties=new Properties(); - properties.setProperty("kaptcha.border.color", "white"); - properties.setProperty("kaptcha.border", "no"); - properties.setProperty("kaptcha.image.width", "125"); - properties.setProperty("kaptcha.image.height", "40"); - properties.setProperty("kaptcha.session.key", "code"); - properties.setProperty("kaptcha.textproducer.char.space", "4"); - properties.setProperty("kaptcha.textproducer.char.length", "4"); - properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); - Config config=new Config(properties); - defaultKaptcha.setConfig(config); - return defaultKaptcha; - } - } diff --git a/tamguo-oms/src/main/java/com/tamguo/config/image/CaptchaUtils.java b/tamguo-oms/src/main/java/com/tamguo/config/image/CaptchaUtils.java new file mode 100644 index 0000000..b5b44b7 --- /dev/null +++ b/tamguo-oms/src/main/java/com/tamguo/config/image/CaptchaUtils.java @@ -0,0 +1,181 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.tamguo.config.image; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Random; + +import org.patchca.background.BackgroundFactory; +import org.patchca.color.ColorFactory; +import org.patchca.filter.predefined.CurvesRippleFilterFactory; +import org.patchca.filter.predefined.DiffuseRippleFilterFactory; +import org.patchca.filter.predefined.DoubleRippleFilterFactory; +import org.patchca.filter.predefined.MarbleRippleFilterFactory; +import org.patchca.filter.predefined.WobbleRippleFilterFactory; +import org.patchca.font.RandomFontFactory; +import org.patchca.service.ConfigurableCaptchaService; +import org.patchca.text.renderer.BestFitTextRenderer; +import org.patchca.utils.encoder.EncoderHelper; +import org.patchca.word.RandomWordFactory; + +/** + * 验证码工具 + * @author ThinkGem + * @version 2017年12月23日 + */ +public class CaptchaUtils { + + private static Random random = new Random(); + private static ConfigurableCaptchaService ccs; + private static WobbleRippleFilterFactory wrff; // 摆波纹 + private static DoubleRippleFilterFactory doff; // 双波纹 + private static CurvesRippleFilterFactory crff; // 曲线波纹 + private static DiffuseRippleFilterFactory drff; // 漫纹波 + private static MarbleRippleFilterFactory mrff; // 大理石 + + private static void initialize(){ + if (ccs == null){ + synchronized (CaptchaUtils.class) { + if (ccs == null){ + // 配置初始化 + ccs = new ConfigurableCaptchaService(); + + // 设置图片大小 + ccs.setWidth(100); + ccs.setHeight(28); + + // 设置文字数量 + RandomWordFactory wf = new RandomWordFactory(); + wf.setCharacters("ABDEFGHKMNRSWX2345689"); + wf.setMinLength(4); + wf.setMaxLength(4); + ccs.setWordFactory(wf); + + // 设置字体大小 + RandomFontFactory ff = new RandomFontFactory(); + ff.setMinSize(28); + ff.setMaxSize(28); + ccs.setFontFactory(ff); + + // 设置文字渲染边距 + BestFitTextRenderer tr = new BestFitTextRenderer(); + tr.setTopMargin(3); + tr.setRightMargin(3); + tr.setBottomMargin(3); + tr.setLeftMargin(3); + ccs.setTextRenderer(tr); + + // 设置字体颜色 + ccs.setColorFactory(new ColorFactory() { + @Override + public Color getColor(int x) { + int r = random.nextInt(90); + int g = random.nextInt(90); + int b = random.nextInt(90); + return new Color(r, g, b); + } + }); + + // 设置背景 + ccs.setBackgroundFactory(new BackgroundFactory() { + @Override + public void fillBackground(BufferedImage image) { + Graphics graphics = image.getGraphics(); + // 验证码图片的宽高 + int imgWidth = image.getWidth(); + int imgHeight = image.getHeight(); + // 填充为白色背景 + graphics.setColor(Color.WHITE); + graphics.fillRect(0, 0, imgWidth, imgHeight); + // 画 50 个噪点(颜色及位置随机) + for (int i = 0; i < 50; i++) { + // 随机颜色 + int rInt = random.nextInt(100)+50; + int gInt = random.nextInt(100)+50; + int bInt = random.nextInt(100)+50; + graphics.setColor(new Color(rInt, gInt, bInt)); + // 随机位置 + int xInt = random.nextInt(imgWidth - 3); + int yInt = random.nextInt(imgHeight - 2); + // 随机旋转角度 + int sAngleInt = random.nextInt(360); + int eAngleInt = random.nextInt(360); + // 随机大小 + int wInt = random.nextInt(6); + int hInt = random.nextInt(6); + // 填充背景 + graphics.fillArc(xInt, yInt, wInt, hInt, sAngleInt, eAngleInt); + // 画5条干扰线 + if (i % 10 == 0) { + int xInt2 = random.nextInt(imgWidth); + int yInt2 = random.nextInt(imgHeight); + graphics.drawLine(xInt, yInt, xInt2, yInt2); + } + } + } + }); + + // 效果初始化 + wrff = new WobbleRippleFilterFactory(); // 摆波纹 + doff = new DoubleRippleFilterFactory(); // 双波纹 + crff = new CurvesRippleFilterFactory(ccs.getColorFactory()); // 曲线波纹 + drff = new DiffuseRippleFilterFactory(); // 漫纹波 + mrff = new MarbleRippleFilterFactory(); // 大理石 + + } + } + } + } + + /** + * 生成验证码 + * @param request + * @param response + * @throws IOException + * @return 验证码字符 + */ + public static String generateCaptcha(OutputStream outputStream) throws IOException{ + + // 初始化设置 + initialize(); + + // 随机选择一个样式 + switch (random.nextInt(3)) { + case 0: + ccs.setFilterFactory(wrff); // 摆波纹 + break; + case 1: + ccs.setFilterFactory(doff); // 双波纹 + break; + case 2: + ccs.setFilterFactory(crff); // 曲线波纹 + break; + case 3: + ccs.setFilterFactory(drff); // 漫纹波 + break; + case 4: + ccs.setFilterFactory(mrff); // 大理石 + break; + } + + // 生成验证码 + String s = EncoderHelper.getChallangeAndWriteImage(ccs, "png", outputStream); +// System.out.println(s); + + return s; + } + +// public static void main(String[] args) throws IOException { +// +// FileOutputStream fos = new FileOutputStream("x:\\captcha.png"); +// String s = generateCaptcha(fos); +// System.out.println(s); +// fos.close(); +// +// } +} diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/TamguoConstant.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/TamguoConstant.java index ed955b5..df91baa 100644 --- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/TamguoConstant.java +++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/TamguoConstant.java @@ -122,4 +122,7 @@ public class TamguoConstant { /** 初始密码*/ public static final String INIT_PASSWORD = "123456"; + + /** 验证码常数*/ + public static final String KAPTCHA_SESSION_KEY = "KAPTCHA_SESSION_KEY"; } diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java index 77a6221..984f816 100644 --- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java +++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/LoginController.java @@ -16,10 +16,10 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; -import com.google.code.kaptcha.Constants; import com.tamguo.modules.sys.utils.ExceptionSupport; import com.tamguo.modules.sys.utils.Result; import com.tamguo.modules.sys.utils.ShiroUtils; +import com.tamguo.modules.sys.utils.TamguoConstant; @Controller public class LoginController { @@ -37,7 +37,7 @@ public class LoginController { public Result toLogin(HttpServletRequest request, String username, String password, String validCode) throws IOException { try { - String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY); + String kaptcha = ShiroUtils.getKaptcha(TamguoConstant.KAPTCHA_SESSION_KEY); if (!validCode.equalsIgnoreCase(kaptcha)) { return Result.failResult("验证码错误"); } diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java index b73a681..d12d487 100644 --- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java +++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/web/ValidCodeController.java @@ -1,48 +1,36 @@ package com.tamguo.modules.sys.web; -import java.awt.image.BufferedImage; import java.io.IOException; - -import javax.imageio.ImageIO; import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; -import com.google.code.kaptcha.Constants; -import com.google.code.kaptcha.Producer; +import com.tamguo.config.image.CaptchaUtils; import com.tamguo.modules.sys.utils.ExceptionSupport; import com.tamguo.modules.sys.utils.ShiroUtils; +import com.tamguo.modules.sys.utils.TamguoConstant; @Controller public class ValidCodeController { - @Autowired - private Producer producer; - @RequestMapping("validCode") - public void validCode(HttpServletResponse response) throws ServletException, IOException { + public void validCode(HttpServletRequest request , HttpServletResponse response) throws ServletException, IOException { response.setHeader("Cache-Control", "no-store, no-cache"); response.setContentType("image/jpeg"); - // 生成文字验证码 - String text = producer.createText(); - // 生成图片验证码 - BufferedImage image = producer.createImage(text); - // 保存到shiro session - ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text); - ServletOutputStream out = response.getOutputStream(); - ImageIO.write(image, "jpg", out); + + String a = CaptchaUtils.generateCaptcha(response.getOutputStream()); + ShiroUtils.setSessionAttribute(TamguoConstant.KAPTCHA_SESSION_KEY, a); } @RequestMapping("checkCode") @ResponseBody public Boolean checkCode(String validCode) throws ServletException, IOException { try { - String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY); + String kaptcha = ShiroUtils.getKaptcha(TamguoConstant.KAPTCHA_SESSION_KEY); if (validCode.equalsIgnoreCase(kaptcha)) { return true; }