ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用简单运算进行登录验证

2021-10-27 22:06:18  阅读:144  来源: 互联网

标签:ch 运算 登录 验证 int random nextInt new String


需求:使用简单的加减乘除运算进行后端系统的登录验证。

效果:

为避免数字 0 出现在除法运算的除数的位置,我们仅支持加减乘三种运算,由于是后台内部人员使用的系统,所以没做太难的处理。

具体的代码实现和上一篇文章基本相同 图片验证码_jiaomubai的博客-CSDN博客

同样提供两个接口:

1.获取验证码接口:

import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@Slf4j
public class CaptchaUtils {

    private static int width = 75;
    private static int height = 35;

    private static char[] ch = "0123456789".toCharArray();
    private static char[] sf = "+-x".toCharArray();


    public static Map getCaptcha() throws Exception {
        // 在内存中创建图象
        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.PLAIN, 18));

        // 画边框
        // g.setColor(new Color());
        // g.drawRect(0,0,width-1,height-1);

        // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
        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);
        }

        // 取随机产生的认证码(4位数字)
        StringBuffer sb = new StringBuffer();
        int index, len = ch.length;
        index = random.nextInt(len);
        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
                random.nextInt(255)));
        g.setFont(new Font("Arial", Font.ITALIC, 20));// 输出的字体和大小
        g.drawString("" + ch[index], (0 * 15), 26);// 写什么数字,在图片的什么位置画
        sb.append(ch[index]);

        int index1, len1 = sf.length;
        index1 = random.nextInt(len1);
        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
                random.nextInt(255)));
        g.setFont(new Font("Arial", Font.ITALIC, 20));// 输出的字体和大小
        g.drawString("" + sf[index1], (1 * 15), 26);// 写什么数字,在图片的什么位置画
        sb.append(sf[index1]);


        int index2, len2 = ch.length;
        index2 = random.nextInt(len2);
        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
                random.nextInt(255)));
        g.setFont(new Font("Arial", Font.ITALIC, 20));// 输出的字体和大小

        if(String.valueOf(sf[index1]).equals("-")){
            if(Integer.parseInt(String.valueOf(ch[index])) < Integer.parseInt(String.valueOf(ch[index2]))){
                index2 = index;
            }
        }

        g.drawString("" + ch[index2], (2 * 15) , 26);// 写什么数字,在图片的什么位置画
        sb.append(ch[index2]);


        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
                random.nextInt(255)));
        g.setFont(new Font("Arial", Font.ITALIC, 20));// 输出的字体和大小
        g.drawString("=", (3 * 15) , 26);// 写什么数字,在图片的什么位置画
        sb.append("=");

        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
                random.nextInt(255)));
        g.setFont(new Font("Arial", Font.ITALIC, 20));// 输出的字体和大小
        g.drawString("?", (4 * 15) , 26);// 写什么数字,在图片的什么位置画
        sb.append("?");

        g.drawLine(5, 3, 60, 35);
        Map<String, Object> result = new HashMap<>();
        int jg = 0;
        if(String.valueOf(sf[index1]).equals("+")){
            jg = Integer.parseInt(String.valueOf(ch[index])) + Integer.parseInt(String.valueOf(ch[index2]));
        }
        if(String.valueOf(sf[index1]).equals("-")){
            jg = Integer.parseInt(String.valueOf(ch[index])) - Integer.parseInt(String.valueOf(ch[index2]));
        }
        if(String.valueOf(sf[index1]).equals("x")){
            jg = Integer.parseInt(String.valueOf(ch[index])) * Integer.parseInt(String.valueOf(ch[index2]));
        }

        // 图象生效
        g.dispose();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        String base64 = "";
        try {
            // 输出图象到页面
            ImageIO.write(image, "JPEG", stream);
            BASE64Encoder encoder = new BASE64Encoder();
            base64 = encoder.encodeBuffer(stream.toByteArray());
            base64 = base64.replaceAll("\n", "").replaceAll("\r", "");
            result.put("result", jg);
            result.put("image", "data:image/png;base64," + base64);
        } catch (IOException e) {
            log.info("生成图片验证码异常", e);
            throw e;
        } finally {
            if (stream != null) {
                stream.flush();
                stream.close();
            }
        }
        return result;
    }

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

以上工具类来源于网络,具体的实现没做详细研究。下面是正式的获取验证码接口:

@RequestMapping("/getCode")
public ResultVO getCode(HttpServletResponse response) {
    Map<String, String> result = new HashMap<>();
    try {
        // 获取图片
        Map<String, Object> imageMap = CaptchaUtils.getCaptcha();
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        int imageResult = (int)imageMap.get("result");
        logger.info("图片验正码计算结果为:{}", imageResult);
        String codeKey = UUID.randomUUID().toString();
        redisSupport.set(codeKey, imageResult);
        result.put("code",(String) imageMap.get("image"));
        result.put("codeKey", codeKey);
    } catch (Exception e) {
        logger.error("生成图片验正码异常", e);
        return new ResultVO<>(ResultVO.FAIL, "获取图片验正码失败");
    }
    return new ResultVO<>(result, ResultVO.SUCCESS, "获取图片验正码成功");
}

其中使用到的 CaptchaUtils 工具就是第一部分展示的工具类。其中使用的 redisSupport 可根据实际情况进行替换,其实就是 Redis 的一个工具包,后续会单独贴出来。

2.登录接口

@PostMapping("/login")
public void login(@RequestParam("username") String username, @RequestParam("password") String password, @RequestParam("code") Integer code, @RequestParam("codeKey") String codeKey, HttpServletResponse resp, HttpServletRequest request) {
    JSONObject result = new JSONObject();
    try {
        Integer redisCode = (Integer) redisSupport.get(codeKey);
        log.info("redisCode:{}",redisCode);
        if(ObjectUtils.isEmpty(code)  || ObjectUtils.isEmpty(redisCode) || !code.equals(redisCode)){
            result.put("error_description", "验证结果错误,请重新输入");
            result.put("error", "invalid_grant");
            resp.setStatus(400);
            redisSupport.del(codeKey);
            return;
        }
    } catch (Exception e) {
        log.error("登录接口错误,错误信息:{}", e);
    } finally {
        try {
            resp.setContentType(ContentType.JSON.getValue());
            ServletOutputStream out = resp.getOutputStream();
            OutputStreamWriter ow = new OutputStreamWriter(out, "UTF-8");
            ow.write(result.toJSONString());
            ow.flush();
            ow.close();
        } catch (Exception e) {
            log.error("登录接口错误,错误信息:{}", e);
        }
    }
}

其中入参中 username 为登录的用户名,password 为登录密码,code 为用户输入的图片验证码的答案,codekey 为与 code 关联的 key,因为在获取验证码的接口中(/getCode)我们已经将 code 和 codekey 存储在了 Redis 中,所以此处可直接根据 codekey 去获取 Redis 中的与 codekey 对应的验证码,之后与用户输入的 code 进行比较即可。其中使用的 redisSupport 可根据实际情况进行替换,其实就是 Redis 的一个工具包,下一篇文章会单独贴出来。

标签:ch,运算,登录,验证,int,random,nextInt,new,String
来源: https://blog.csdn.net/jiaomubai/article/details/121002999

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有