1、生成图片验证码的步骤
1.根据随机数生成数字
2.将随机数存到Session中
3.将生成的图片写到接口的响应中html
public class ImageCode { private BufferedImage image;//展现的图片 private String code;//生成的随机数,Session private LocalDateTime expireTime;//过时时间 public BufferedImage getImage() { return image; } public void setImage(BufferedImage image) { this.image = image; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public LocalDateTime getExpireTime() { return expireTime; } public void setExpireTime(LocalDateTime expireTime) { this.expireTime = expireTime; } //是否过时 public boolean isExpried() { return LocalDateTime.now().isAfter(expireTime); } public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) { this.image = image; this.code = code; this.expireTime = expireTime; } //多少秒过时(60秒) public ImageCode(BufferedImage image, String code, int expireIn) { this.image = image; this.code = code; this.expireTime = LocalDateTime.now().plusSeconds(expireIn); } }
@RestController public class ValidateCodeController { private static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE"; //操做Session的类 private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); @GetMapping("/code/image") public void createCode(HttpServletRequest request,HttpServletResponse response) throws IOException { //1.根据随机数生成数字 ImageCode imageCode = createImageCode(request); //2.将随机数存到Session中 //把请求传递进ServletWebRequest, sessionStrategy.setAttribute(new ServletWebRequest(request), SESSION_KEY, imageCode); //3.将生成的图片写到接口的响应中 ImageIO.write(imageCode.getImage(), "JPEG", response.getOutputStream()); } //生成图片 private ImageCode createImageCode(HttpServletRequest request) { int width = 67; int height = 23; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics graphics = image.getGraphics(); Random random = new Random(); graphics.setColor(getRandColor(200,250)); graphics.fillRect(0, 0, width, height); graphics.setFont(new Font("Times New Roman", Font.ITALIC, 20)); graphics.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); graphics.drawLine(x, y, x+xl, y+yl); } String sRand = ""; for (int i = 0; i < 4; i++) { String rand = String.valueOf(random.nextInt(10)); sRand +=rand; graphics.setColor(new Color(20, random.nextInt(110), 20+random.nextInt(110),20+random.nextInt(110))); graphics.drawString(rand, 13*i+6, 16); } graphics.dispose(); return new ImageCode(image, sRand, 60); } //随机生成背景条纹 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); } }
前台登陆页面增长图形验证码样式安全
其次,再安全配置类;增长/code/image请求的session
.antMatchers("/code/image").permitAll()
2、运行项目
在点击登陆按钮以前,须要处理校验码校验的逻辑这一步骤,这个步骤放在UsernamePasswordAuthenticationFilter以前,因此说,在安全配置类里面需求写一个自定义的Filter而且加在Username xx以前
最后启动项目,访问:http://localhost:8080/sign.htmlapp
在不输入验证码的时候,点击登陆能够看到它把异常栈里面的全部错误信息都打印出来了
这个并非咱们想要的,这个时候须要修改一下失败处理器AuthenticationFailureHandler
把返回全部堆栈信息的方法,改为只返回错误信息。
还有一个问题,就是验证码错误的时候过滤器没有作拦截,而是继续往下走了,这个时候须要更改Filter的方法dom
启动项目,访问:http://localhost:8080/sign.html
再不输入验证码的时候,点击登陆
能够直接看到错误信息
同理,以后继续填写正确的验证码,则能够获得对应的用户信息
输入错误,则有对应错误的消息提示,这个时候 验证码的功能才算是完成了。ide