JAVA实现图片验证

2020-08-02 来源: 遮天科技 发布在  https://www.cnblogs.com/zhetiankj/p/12661374.html

一、什么是图片验证码?

可以参考下面这张图:

我们在一些网站登陆的时候,经常需要填写以上图片的信息。

这种图片验证方式是我们最常见的形式,它可以有效的防范恶意攻击者采用恶意工具,来进行窃取用户的密码

接下来将讲正题啦!

1.首先得有一个生成图片验证码的实体类

package com.zhetian.www.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * @Copyright (C)遮天网络有限公司
 * @Author: YUAN HUAI XING
 * @qq联系方式: 11234013
 * @Date 2020/4/5 18:09
 * @Descripthion:
 **/

public class ImageVerificationCodeUtil {
    private int weight = 100;           //验证码图片的长和宽
    private int height = 40;
    private String text;                //用来保存验证码的文本内容
    private Random r = new Random();    //获取随机数对象
    //private String[] fontNames = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};   //字体数组
    //字体数组
    private String[] fontNames = {"Georgia"};
    //验证码数组
    private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";

    /**
     * 获取随机的颜色
     *
     * @return
     */
    private Color randomColor() {
        int r = this.r.nextInt(225);  //这里为什么是225,因为当r,g,b都为255时,即为白色,为了好辨认,需要颜色深一点。
        int g = this.r.nextInt(225);
        int b = this.r.nextInt(225);
        return new Color(r, g, b);            //返回一个随机颜色
    }

    /**
     * 获取随机字体
     *
     * @return
     */
    private Font randomFont() {
        int index = r.nextInt(fontNames.length);  //获取随机的字体
        String fontName = fontNames[index];
        int style = r.nextInt(4);         //随机获取字体的样式,0是无样式,1是加粗,2是斜体,3是加粗加斜体
        int size = r.nextInt(10) + 24;    //随机获取字体的大小
        return new Font(fontName, style, size);   //返回一个随机的字体
    }

    /**
     * 获取随机字符
     *
     * @return
     */
    private char randomChar() {
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }

    /**
     * 画干扰线,验证码干扰线用来防止计算机解析图片
     *
     * @param image
     */
    private void drawLine(BufferedImage image) {
        int num = r.nextInt(10); //定义干扰线的数量
        Graphics2D g = (Graphics2D) image.getGraphics();
        for (int i = 0; i < num; i++) {
            int x1 = r.nextInt(weight);
            int y1 = r.nextInt(height);
            int x2 = r.nextInt(weight);
            int y2 = r.nextInt(height);
            g.setColor(randomColor());
            g.drawLine(x1, y1, x2, y2);
        }
    }

    /**
     * 创建图片的方法
     *
     * @return
     */
    private BufferedImage createImage() {
        //创建图片缓冲区
        BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB);
        //获取画笔
        Graphics2D g = (Graphics2D) image.getGraphics();
        //设置背景色随机
        g.setColor(new Color(255, 255, r.nextInt(245) + 10));
        g.fillRect(0, 0, weight, height);
        //返回一个图片
        return image;
    }

    /**
     * 获取验证码图片的方法
     *
     * @return
     */
    public BufferedImage getImage() {
        BufferedImage image = createImage();
        Graphics2D g = (Graphics2D) image.getGraphics(); //获取画笔
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 4; i++)             //画四个字符即可
        {
            String s = randomChar() + "";      //随机生成字符,因为只有画字符串的方法,没有画字符的方法,所以需要将字符变成字符串再画
            sb.append(s);                      //添加到StringBuilder里面
            float x = i * 1.0F * weight / 4;   //定义字符的x坐标
            g.setFont(randomFont());           //设置字体,随机
            g.setColor(randomColor());         //设置颜色,随机
            g.drawString(s, x, height - 5);
        }
        this.text = sb.toString();
        drawLine(image);
        return image;
    }

    /**
     * 获取验证码文本的方法
     *
     * @return
     */
    public String getText() {
        return text;
    }

    public static void output(BufferedImage image, OutputStream out) throws IOException                  //将验证码图片写出的方法
    {
        ImageIO.write(image, "JPEG", out);
    }

}

2.在控制器中把图片响应给前端页面(ssm框架)

 /**
     * 图片随机码
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/getVerifiCode")
    public void getVerifiCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /*
             1.生成验证码
             2.把验证码上的文本存在session中
             3.把验证码图片发送给客户端
             */
        ImageVerificationCodeUtil ivc = new ImageVerificationCodeUtil();     //用我们的验证码类,生成验证码类对象
        BufferedImage image = ivc.getImage();  //获取验证码
        String text = ivc.getText(); //获取随机码
        HttpSession session = request.getSession();
        session.setAttribute("imgcode", text); //将随机码的文本存在session中
        System.out.println("文字随机码:"+text);
        ImageVerificationCodeUtil.output(image, response.getOutputStream());//将验证码图片响应给客户端
    }
3、从session获得验证码字符(ssm框架)
  /**
     * 登陆功能:接收用户输入的用户名跟密码(接收参数)
     * @param loginUser
     * @return
     */
    @RequestMapping("/pageData")
    @ResponseBody
    public Result pageData(LoginUser loginUser,String code,HttpServletRequest request){
        HttpSession session = request.getSession();
        //获取随机数
        String imgcode = (String)session.getAttribute("imgcode");
        //调用业务方法
        Result<LoginUser> result= loginUserService.loginUserByuserName(loginUser, code,imgcode);
        return result;
    }
4、业务层(Service)
 /**
     * 获取用户输入的用户名与数据库进行对比是否一致
     * 如果一致在获取密码对比是否一致
     * 都一致再对比图片验证码与用户输入的是否一致
     * @param loginUser
     * @return
     */
    @Override
    public Result loginUserByuserName(LoginUser loginUser,String code,String imgcode) {
        Result<LoginUser> result = new Result<>();
        String userName = loginUser.getUserName();
        LoginUser loginUser1 = loginUserDao.loginUserByuserName(userName);
        if (code != null && code.equals(imgcode)) {
            if (loginUser1 != null) {
                String password = loginUser.getPassword();
                String password1 = loginUser1.getPassword();
                if (password != null && password1 != null && password1.equals(password)) {
                    result.setCode("0000");
                    result.setData(loginUser);
                    return result;
                } else {
                    result.setCode("0001");
                    result.setMsg("用户名或密码错误!请检查后重新登陆!");
                    result.setSuccess(false);
                    return result;
                }
            } else {
                result.setCode("0002");
                result.setMsg("用户名不存在!请检查用户名后重新登陆!");
                result.setSuccess(false);
                return result;
            }
        }else {
            result.setCode("0005");
            result.setMsg("验证码不正确!");
            result.setSuccess(false);
            return result;
        }

    }


5、前端代码
 <div class="form-group">
                                <%--<label for="password">请输入验证码--%>
                                </label>
                                <input id="code" type="text" class="form-control" name="code" width="400px" placeholder="请输入验证码">
                                <a href="javascript:getVerifiCode()">
                                    <img id="yzm_img" style="cursor:pointer;width: 100px;height: 40px;margin: 0px 0 0 5px;
                                    border-radius: 3px;"
                                         title="点击刷新验证码" src="/login/getVerifiCode" />
                                </a>
                            </div>
    function pageData() {
        var code=$("#code").val();
        var userName=$("#userName").val();
        var password=$("#password").val();
        var aa = $("input[type='checkbox']").is(":checked");//获取选中状态
        if(userName == ''){
            alert("请输入用户名。");
            return;
        }
        if(password == ''){
            alert("请输入密码。");
            return;
        }
        if(aa==true){
            setCookie();   //调用设置Cookie的方法
        }else if(aa==false){
            setCookie();  //调用设置Cookie的方法
        }

        var params = {
            userName:userName,
            password:password,
            code:code
        };
        var url = '/login/pageData';
        jQuery.ajax({
            type: 'POST',
            contentType: 'application/x-www-form-urlencoded',
            url: url,
            data: params,
            dataType: 'json',
            success: function (data) {
                // alert("成功啦");
                var code=data.code;
                if (code=="0000"){
                    alert("登陆成功!")
                    location.href="/tick/list";
                } else if(code=="0001"){
                    alert("登陆提示:"+data.msg);
                }else if(code=="0002"){
                    alert("登陆提示:"+data.msg);
                }else if(code=="0005"){
                    alert("登陆提示:"+data.msg);
                }else {
                    alert("未知异常!");
                }

            },
            error: function (data) {
                alert("失败啦");
            }
        });
    }



好了,这就是基本上实现的步骤,最后再上几张实现效果图↑↑↑↑↑
@注:本博客仅为个人学习笔记。 所属人:Yuan 

相关文章