spring-Security(五):图形验证码

图形验证码整体流程大概是:
  1. 页面初始化的时候服务器生成一个验证码,然后将验证码保存到session中,再显示给html(客户端)
  2. 整合springsecurity校验,自定义一个filter,将该filter设置在UsernamePasswordAuthenticationFilter之前执行,这样就会在验证用户名密码之前就校验验证码
  3. 在我第三步我们自定义的filter里面校验html传来的验证码和第二步我们保存到session的验证码是否想要,如果相同那么就放行,验证成功

接下来我们看看每一步的代码具体怎么实现

  •     页面初始化的时候服务器生成一个验证码,然后将验证码保存到session中,再显示给html(客户端)

首先我们得新建一个类ImageCode用来存放验证码信息

public class ImageCode {
   private BufferedImage image;
    private  String code;
    private LocalDateTime expireTime;//过期时间
    /**
     *
     * @param image
     * @param code
     * @param expireInt :该参数是过期时间秒数,如60
     */
    public ImageCode(BufferedImage image, String code, int expireInt) {
        this.image = image;
        this.code = code;
        this.expireTime = LocalDateTime.now().plusSeconds(expireInt);//当前时间加上60秒
    }
 }

然后生成一个验证码(ImageCode)对象

package org.spring.springcloud.config.springSecurity;


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;



@RestController
public class ImageCodeController {

   // private  SessionStrategy sessionStrategy=new HttpSessionSessionStrategy();

    @RequestMapping(value="/imageCode" ,method = RequestMethod.GET)
    public void imageCode(HttpServletRequest request , HttpServletResponse response,HttpSession session) throws IOException {
        //生成imageCode对象
        ImageCode imageCode=createImageCode();
        //将图形验证码存入到session中
        request.getSession().setAttribute("imageCode",imageCode);
        // 将生成的图片写到接口的响应中
        ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream());

    }

    private ImageCode createImageCode() {
        int width=80;
        int height=30;
        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 code = "";
        for (int i = 0; i < 4; i++) {
            String rand = String.valueOf(random.nextInt(10));
            code += 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, code, 60);
    }
    /**
     * 生成随机背景条纹
     *
     * @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);
    }


}

  • 整合springsecurity校验,自定义一个filter,将该filter设置在UsernamePasswordAuthenticationFilter之前执行,这样就会在验证用户名密码之前就校验验证码

package org.spring.springcloud.config.springSecurity.filter;


import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
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 javax.servlet.http.HttpSession;
import java.io.IOException;

@Component
public class ValidateCodefilter extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
       String uri= request.getRequestURI();
        //如果为get请求并且请求uri为/login(也就是我们登录表单的form的action地址)
        if( StringUtils.equalsIgnoreCase(request.getMethod(),"get") && StringUtils.containsIgnoreCase(request.getRequestURI(),"/login"))
        {
            logger.info("ValidateCodefilter执行了----" + "request.getRequestURI()=" + uri);
            //这里需要验证前端传过来的验证码是否和session里面存的一致,并且要判断是否过期
            logger.info(request.getSession().getAttribute("imageCode"));
            validateCode(request);

        }

        filterChain.doFilter(request,response);
    }

    /**
     * 验证用户输入的验证码和session中存的是否一致
     * @param request
     */
    private void validateCode(HttpServletRequest request) {
           
    }


}

在securiryConfig文件中将该filter设置在UsernamePasswordAuthenticationFilter之前执行

http.addFilterBefore(validateCodefilter,UsernamePasswordAuthenticationFilter.class);

验证码功能到这里就完成了

猜你喜欢

转载自blog.csdn.net/liyu121/article/details/80527659
今日推荐