【spring security】springsecurity json 验证码

前言

spring security实现json请求的图形验证码

思路

基础实现:
我这边是参考的朱古力大佬的代码https://github.com/wuyouzhuguli/SpringAll/tree/master/36.Spring-Security-ValidateCode
直接用。
但是,他这个是适用于表单请求的。
为什么这么说呢?主要在于这一行:
在这里插入图片描述
获取验证码的时候,如果是表单提交,这里是可以正常获取,下面流程继续跑,是可以的。
但是如果是json请求,那么久需要从servletWebRequest里面通过流去获取传的验证码了。
但是,流里面的参数只能使用一次,这里使用了,到userDetailService,验证用户账号密码的时候,就会获取不到参数了。
具体原因,以及示例可以参考这里:https://blog.csdn.net/s1441101265/article/details/113180129

解决办法

无意间看到这篇文章:https://github.com/liuyatao/spring_security_verifycode
这一块代码:
在这里插入图片描述看到他是在这里验证的。然后我看了下代码,发现这里是在验证用户登录userDetailsService之前的逻辑。
所以我也在这里调用了下验证图形验证码的方法:

ValidateCodeUtil.checkImageCode(request, authenticationBean.getImageCode());

ValidateCodeUtil

import com.website.server.system.component.security.image.bean.ImageCode;
import com.website.server.system.component.security.image.exception.ValidateCodeException;
import org.apache.commons.lang.StringUtils;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.context.request.ServletWebRequest;

import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * @author :qilong sun
 * @date :Created in 2021/1/25 14:36
 * @description:图片验证码工具类
 * @modified By:
 * @version: V1.0$
 */
public class ValidateCodeUtil {
    
    
    /**
     * 图形验证码存储在session中的key
     */
    public final static String SESSION_KEY_IMAGE_CODE = "SESSION_KEY_IMAGE_CODE";

    /**
     * 验证图片二维码
     *
     * @param request
     * @param imageCode
     */
    public static void checkImageCode(HttpServletRequest request, String imageCode) {
    
    
        // 获取sessionStrategy
        SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
        // 获取sessionStrategy中 的imageCode对象
        ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(new ServletWebRequest(request), ValidateCodeUtil.SESSION_KEY_IMAGE_CODE);
        if (StringUtils.isBlank(imageCode)) {
    
    
            throw new ValidateCodeException("验证码不能为空!");
        }
        if (codeInSession == null) {
    
    
            throw new ValidateCodeException("验证码不存在!");
        }
        if (codeInSession.isExpire()) {
    
    
            sessionStrategy.removeAttribute(new ServletWebRequest(request), ValidateCodeUtil.SESSION_KEY_IMAGE_CODE);
            throw new ValidateCodeException("验证码已过期!");
        }
        if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), imageCode)) {
    
    
            throw new ValidateCodeException("验证码不正确!");
        }
        sessionStrategy.removeAttribute(new ServletWebRequest(request), ValidateCodeUtil.SESSION_KEY_IMAGE_CODE);
    }

    /**
     * 创建image验证码
     *
     * @return
     */
    public static ImageCode createImageCode() {
    
    
        /**
         * 验证码图片宽度
         */
        int width = 100;
        /**
         * 验证码图片长度
         */
        int height = 36;
        /**
         * 验证码位数
         */
        int length = 4;
        /**
         * 验证码有效时间 60s
         */
        int expireIn = 60;

        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);
        }

        StringBuilder sRand = new StringBuilder();
        for (int i = 0; i < length; i++) {
    
    
            String rand = String.valueOf(random.nextInt(10));
            sRand.append(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.toString(), expireIn);
    }

    /**
     * 获取随机颜色
     *
     * @param fc
     * @param bc
     * @return
     */
    public static 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);
    }
}

成功!
但是感觉有点问题,因为存储验证码到session的key是同一个,这就有可能导致自己的验证码被别人刷失效,这个问题后面再研究

猜你喜欢

转载自blog.csdn.net/s1441101265/article/details/113848602