|
控制层实现:
public static final String SESSION_CODE_KEY_1 = "SESSION_KEY_IMAGE_CODE_1"; /** * 模拟用户登录时的数字算数验证码 * @param response * @return */ @RequestMapping(value="/verifyCode", method= RequestMethod.GET) @ResponseBody public void getVerifyCode(HttpServletRequest request,HttpServletResponse response) { try { ImageCode imageCode = testService.createVerifyCode(request); //存入session request.getSession().setAttribute(SESSION_CODE_KEY_1,imageCode); ImageIO.write(imageCode.getImage(), "JPEG", response.getOutputStream()); }catch(Exception e) {} } |
服务层实现:
/** * Created by xingyuchao on 2018/4/23. */ @Service public class TestService { @Autowired CodeProperties codeProperties; //定义运算符 private static char[] ops = new char[] {'+', '-', '*'}; /** * 生成验证码 * @return */ public ImageCode createVerifyCode(HttpServletRequest request) { //create the image BufferedImage image = new BufferedImage(codeProperties.getWidth(), codeProperties.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); // set the background color g.setColor(new Color(0xDCDCDC)); g.fillRect(0, 0, codeProperties.getWidth(), codeProperties.getHeight()); // draw the border g.setColor(Color.black); g.drawRect(0, 0, codeProperties.getWidth() - 1, codeProperties.getHeight() - 1); // create a random instance to generate the codes Random rdm = new Random(); // make some confusion for (int i = 0; i < 50; i++) { int x = rdm.nextInt(codeProperties.getWidth()); int y = rdm.nextInt(codeProperties.getHeight()); g.drawOval(x, y, 0, 0); } // generate a random code String verifyCode = generateVerifyCode(rdm); g.setColor(new Color(0, 100, 0)); g.setFont(new Font("Candara", Font.BOLD, 24)); g.drawString(verifyCode, 8, 24); g.dispose(); //计算验证码结果 int rnd = calc(verifyCode); //将运算结果存到redis中 //redisService.set("verifyCode:"+user.getId(),60, rnd); //输出图片 return new ImageCode(image, rnd+"", codeProperties.getExpireIn()); } /** * 4+2-7 组合算数 * + - * * */ private static String generateVerifyCode(Random rdm) { int num1 = rdm.nextInt(10); int num2 = rdm.nextInt(10); int num3 = rdm.nextInt(10); char op1 = ops[rdm.nextInt(3)]; char op2 = ops[rdm.nextInt(3)]; String exp = ""+ num1 + op1 + num2 + op2 + num3; return exp; } /** * 计算结果 * @param exp * @return */ private static int calc(String exp) { try { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); return (Integer)engine.eval(exp); }catch(Exception e) { return 0; } } public static void main(String[] args) { //System.out.println(calc("8*8")); System.out.println(generateVerifyCode(new Random())); } } |
通用属性设置:
/** * 配置文件信息 * 默认配置 */ @Data @Component @ConfigurationProperties(prefix = "dxh.code") public class CodeProperties { /*图片验证码宽度*/ private int width = 70; /*图片验证码高度*/ private int height = 30; /*图片验证码长度4位*/ private int length = 4; /*图片验证码默认过期时间*/ private int expireIn = 60; } |
控制层实现:
public static final String SESSION_CODE_KEY_2 = "SESSION_KEY_IMAGE_CODE_2"; /** * 普通验证码 * @param request * @param response * @throws IOException */ @GetMapping("/image") public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException { //生成图片验证码 ImageCode imageCode = testService.generate(request); //存入session request.getSession().setAttribute(SESSION_CODE_KEY_2,imageCode); //将生成的图片写到响应中 ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream()); } |
服务层实现:
public ImageCode generate(HttpServletRequest request) { int width = ServletRequestUtils.getIntParameter(request, "width", codeProperties.getWidth()); int height = ServletRequestUtils.getIntParameter(request, "height", codeProperties.getHeight()); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); Random random = new Random(); g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, width, height); g.setFont(new Font("Times New Roman", Font.ITALIC, 20)); g.setColor(getRandColor(160, 200)); for (int i = 0; i < 155; i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x + xl, y + yl); } String sRand = ""; for (int i = 0; i < codeProperties.getLength(); i++) { String rand = String.valueOf(random.nextInt(10)); sRand += rand; g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); g.drawString(rand, 13 * i + 6, 16); } g.dispose(); return new ImageCode(image, sRand, codeProperties.getExpireIn()); } /** * 生成随机背景条纹 * * @param fc * @param bc * @return */ private Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } |
html:
HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hellotitle>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
head>
<body>
<h1 align="center">验证码测试h1>
<h3 align="center">算数验证码测试h3>
<form action="/code/checkCode" method="post">
<table align="center">
<tr>
<td>算数验证码:
<input type="text" name="code">
<input type="hidden" name="status" value="1">
<img src="/code/verifyCode?+"×tamp="+new Date().getTime()">
td>
tr>
<tr>
<td align="center" colspan="2"><button type="submit">登录button>td>
tr>
table>
form>
<hr><hr>
<h3 align="center">普通验证码测试h3>
<form action="/code/checkCode" method="post">
<table align="center">
<tr>
<td>普通验证码:
<input type="text" name="code">
<input type="hidden" name="status" value="2">
<img src="/code/image?+"×tamp="+new Date().getTime()">
td>
tr>
<tr>
<td align="center" colspan="2"><button type="submit">登录button>td>
tr>
table>
form>
body>
html>
|
---------------------------------------------------------------------------------------
上面的代码写的有点垃圾,不可扩展,简单的做了下修改
增加校验器接口,一个项目中可以这段时间使用这个验证码,过段时间又换了一种验证码
/** * 校验码生成器接口 * Created by xingyuchao on 2017/12/19. * */ public interface ValidateCodeGenerator { /** * 生成校验码 * @param request * @return */ ImageCode generate(HttpServletRequest request); } |
将两种验证码实现方式抽离出来
/** * Created by xingyuchao on 2018/4/26. * 算术验证码, 默认生成方式 */ @Component("codeGenerator") public class ArithmeticCodeGenerator implements ValidateCodeGenerator { @Autowired private CodeProperties codeProperties; //定义运算符 private static char[] ops = new char[] {'+', '-', '*'}; /** * 生成验证码 * @return */ @Override public ImageCode generate(HttpServletRequest request) { //create the image BufferedImage image = new BufferedImage(codeProperties.getWidth(), codeProperties.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); // set the background color g.setColor(new Color(0xDCDCDC)); g.fillRect(0, 0, codeProperties.getWidth(), codeProperties.getHeight()); // draw the border g.setColor(Color.black); g.drawRect(0, 0, codeProperties.getWidth() - 1, codeProperties.getHeight() - 1); // create a random instance to generate the codes Random rdm = new Random(); // make some confusion for (int i = 0; i < 50; i++) { int x = rdm.nextInt(codeProperties.getWidth()); int y = rdm.nextInt(codeProperties.getHeight()); g.drawOval(x, y, 0, 0); } // generate a random code String verifyCode = generateVerifyCode(rdm); g.setColor(new Color(0, 100, 0)); g.setFont(new Font("Candara", Font.BOLD, 24)); g.drawString(verifyCode, 8, 24); g.dispose(); //计算验证码结果 int rnd = calc(verifyCode); //将运算结果存到redis中 //redisService.set("verifyCode:"+user.getId(),60, rnd); //输出图片 return new ImageCode(image, rnd+"", codeProperties.getExpireIn()); } /** * 4+2-7 组合算数 * + - * * */ private static String generateVerifyCode(Random rdm) { int num1 = rdm.nextInt(10); int num2 = rdm.nextInt(10); int num3 = rdm.nextInt(10); char op1 = ops[rdm.nextInt(3)]; char op2 = ops[rdm.nextInt(3)]; String exp = ""+ num1 + op1 + num2 + op2 + num3; return exp; } /** * 计算结果 * @param exp * @return */ private static int calc(String exp) { try { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); return (Integer)engine.eval(exp); }catch(Exception e) { return 0; } } public static void main(String[] args) { //System.out.println(calc("8*8")); System.out.println(generateVerifyCode(new Random())); } } |
/** * Created by xingyuchao on 2018/4/26. * 普通验证码 */ public class ImageCodeGenerator implements ValidateCodeGenerator { @Autowired CodeProperties codeProperties; @Override public ImageCode generate(HttpServletRequest request) { int width = ServletRequestUtils.getIntParameter(request, "width", codeProperties.getWidth()); int height = ServletRequestUtils.getIntParameter(request, "height", codeProperties.getHeight()); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); Random random = new Random(); g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, width, height); g.setFont(new Font("Times New Roman", Font.ITALIC, 20)); g.setColor(getRandColor(160, 200)); for (int i = 0; i < 155; i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x + xl, y + yl); } String sRand = ""; for (int i = 0; i < codeProperties.getLength(); i++) { String rand = String.valueOf(random.nextInt(10)); sRand += rand; g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); g.drawString(rand, 13 * i + 6, 16); } g.dispose(); return new ImageCode(image, sRand, codeProperties.getExpireIn()); } /** * 生成随机背景条纹 * * @param fc * @param bc * @return */ private Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } public CodeProperties getCodeProperties() { return codeProperties; } public void setCodeProperties(CodeProperties codeProperties) { this.codeProperties = codeProperties; } } |
增加扩展配置
/** * 验证码相关的扩展点配置。配置在这里的bean,业务系统都可以通过声明同类型或同名的bean来覆盖默认的配置。 * Created by xingyuchao on 2018/04/26. * */ @Configuration public class ValidateCodeBeanConfig { @Autowired private CodeProperties codeProperties; /** * 图片验证码图片生成器 * @return */ @Bean @ConditionalOnMissingBean(name = "codeGenerator") public ValidateCodeGenerator codeGenerator() { ImageCodeGenerator codeGenerator = new ImageCodeGenerator(); codeGenerator.setCodeProperties(codeProperties); return codeGenerator; } } |
这样子,换验证方式的时候,只需要将ArithmeticCodeGenerator上的注解注释掉就行