java做图片点击文字验证码

版权声明: https://blog.csdn.net/qq_27721169/article/details/82769093

效果:

import com.datbc.youpinchain.admin.service.ImgCheckService;
import com.datbc.youpinchain.db.util.MD5Utils;
import com.datbc.youpinchain.db.util.ResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/XXXX")
@Slf4j
public class ImgCheckController {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private ImgCheckService imgCheckService;

    private static Random random = new Random();

    @GetMapping("/getImg")
    public void getImg(HttpServletResponse response, String id) {
        int fontSize = 30;
        int height = 290;  //图片高
        int width = 450;  //图片宽
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) image.getGraphics();
        // 读取本地图片,做背景图片
        URL resource = getClass().getResource("/checkImg/" + (random.nextInt(4) + 1) + ".png");
        try {
            g.drawImage(ImageIO.read(new File(resource.getPath())), 0, fontSize, width, height, null); //将背景图片从高度30开始
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        g.setColor(Color.WHITE);  //设置颜色
        g.drawRect(0, 0, width - 1, height - 1); //画边框

        g.setFont(new Font("宋体", Font.BOLD, fontSize)); //设置字体
        Integer x = null;  //用于记录坐标
        Integer y = null;
        String target = null; // 用于记录文字
        for (int i = 0; i < 4; i++) {  //随机产生4个文字,坐标,颜色都不同
            g.setColor(getRandColor(100, 160));
            String str = getRandomChineseChar();
            int a = random.nextInt(width - 100) + 50;
            int b = random.nextInt(height - 100) + 55;

            if (x == null) {
                x = a; //记录第一个x坐标
            }
            if (y == null) {
                y = b;//记录第一个y坐标
            }
            if (target == null) {
                target = str; //记录第一个文字
            }
            g.drawString(str, a, b);
        }

        g.setColor(Color.white);
        g.drawString("请点击:" + target, 0, fontSize);
        redisTemplate.opsForValue().set("XXX:" + MD5Utils.encrypt(id), x + ":" + y, 5, TimeUnit.MINUTES);
        //5.释放资源
        g.dispose();
        //6.利用ImageIO进行输出
        try {
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("image/jpeg");
            ImageIO.write(image, "PNG", response.getOutputStream()); //将图片输出
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 随机产生颜色
     */
    private static Color getRandColor(int fc, int bc) {
        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);
    }

    /**
     * 随机产生汉字
     */
    private String getRandomChineseChar() {
        String str = null;
        int heightPos; // 定义高低位
        int lowPos;
        Random random = new Random();
        heightPos = (176 + Math.abs(random.nextInt(39))); //获取高位值
        lowPos = (161 + Math.abs(random.nextInt(93))); //获取低位值
        byte[] b = new byte[2];
        b[0] = (new Integer(heightPos).byteValue());
        b[1] = (new Integer(lowPos).byteValue());
        try {
            str = new String(b, "GBk"); //转成中文
        } catch (UnsupportedEncodingException ex) {
            log.error(ex.getMessage());
        }
        return str;
    }

    @GetMapping("/checkImg")
    public Object checkImg(String id, String mX, String mY) {
        if (imgCheckService.checkImg(id, mX, mY)) {  //若前端上传的坐标在session中记录的坐标的一定范围内则验证成功
            return ResponseUtil.ok(0);
        } else {
            return ResponseUtil.ok(1);
        }
    }
}
import com.datbc.youpinchain.db.util.MD5Utils;
import com.datbc.youpinchain.db.util.MyString;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class ImgCheckService {

    private static final String KEY = "XXX:";

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    public Boolean checkImg(String id, String mX, String mY) {
        String str = redisTemplate.opsForValue().get(KEY + MD5Utils.encrypt(id));
        if (str == null) {
            return false;
        }
        String[] split2 = str.split(":");
        int x = Integer.parseInt(mX);
        int y = Integer.parseInt(mY);
        int x1 = Integer.parseInt(split2[0]);
        int y1 = Integer.parseInt(split2[1]);
        return x1 - 22 < x && x < x1 + 22 && y1 - 22 < y && y < y1 + 22;
    }

    public Boolean checkImg(String imgCheckArr) {
        if (MyString.isEmpty(imgCheckArr)) {
            return false;
        }
        String[] imgChecks = imgCheckArr.split(":");
        if (imgChecks.length != 3) {
            return false;
        }
        return checkImg(imgChecks[0], imgChecks[1], imgChecks[2]);
    }

    public void removeRedis(String imgCheckArr) {
        if (!MyString.isEmpty(imgCheckArr)) {
            String[] imgChecks = imgCheckArr.split(":");
            if (imgChecks.length == 3) {
                redisTemplate.delete(KEY + MD5Utils.encrypt(imgChecks[0]));
            }
        }
    }
}

前台:

<el-form-item prop="imgCheck" v-show="loginForm.username !== '' && loginForm.password !== ''">
        <el-input name="imgCheck" type="text" v-model="loginForm.imgCheck" autoComplete="on" placeholder="imgCheck" v-show="false"></el-input>
        <img @click="getImgEvent($event)" :src="getImg" v-show="isShow"/>
        <span style="color:#ff4546">{{imgCheckText}}</span>
        <span style="color:#3464ff" @click="refreshImg" v-show="isShow">看不清?换一张</span>
      </el-form-item>


 methods: {
    getImgEvent(event) {
      var that = this
      var mX = event.offsetX
      var mY = event.offsetY
      var id = that.getImgId
      const data = {
        id,
        mX,
        mY
      }

猜你喜欢

转载自blog.csdn.net/qq_27721169/article/details/82769093