java web图片验证码

硅谷探秘者 2306 0 0

java web图片验证码


1.验证码的作用:

        防止恶意破解密码、刷票、论坛灌水、刷页。

        有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录尝试,实际上使用验证码是现在很多网站通行的方式(比如招商银行的网上个人银行,百度社区),我们利用比较简易的方式实现了这个功能。虽然登录麻烦一点,但是对网友的密码安全来说这个功能还是很有必要,也很重要。但我们还是 提醒大家要保护好自己的密码 ,尽量使用混杂了数字、字母、符号在内的6位以上密码,不要使用诸如1234之类的简单密码或者与用户名相同、类似的密码 ,免得你的账号被人盗用给自己带来不必要的麻烦。

        验证码通常使用一些线条和一些不规则的字符组成,主要作用是为了防止一些黑客把密码数据化盗取。


menu.saveimg.savepath20190309145650.jpg


2.服务端

2.1.验证码生成工具类

package com.dzqc.dz.common.controller;
import javax.imageio.ImageIO;  
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.OutputStream;  
import java.util.Date;  
import java.util.Random;  
/** 
 * 验证码生成工具类
 */  
public class ValidateCode {  
    // 图片的宽度。  
    private int width = 160;  
    // 图片的高度。  
    private int height = 40;  
    // 验证码字符个数  
    private int codeCount = 5;  
    // 验证码干扰线数  
    private int lineCount = 150;  
    // 验证码  
    private String code = null;  
    // 验证码图片Buffer  
    private BufferedImage buffImg = null;  
  
    // 验证码范围,去掉0(数字)和O(拼音)容易混淆的(小写的1和L也可以去掉,大写不用了)  
    private char[] codeSequence = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',  
            'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',  
            'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9'};  
  
    /** 
     * 默认构造函数,设置默认参数 
     */  
    public ValidateCode() {  
        this.createCode();  
    }  
  
    /** 
     * @param width  图片宽 
     * @param height 图片高 
     */  
    public ValidateCode(int width, int height) {  
        this.width = width;  
        this.height = height;  
        this.createCode();  
    }  
  
    /** 
     * @param width     图片宽 
     * @param height    图片高 
     * @param codeCount 字符个数 
     * @param lineCount 干扰线条数 
     */  
    public ValidateCode(int width, int height, int codeCount, int lineCount) {  
        this.width = width;  
        this.height = height;  
        this.codeCount = codeCount;  
        this.lineCount = lineCount;  
        this.createCode();  
    }  
  
    public void createCode() {  
        int x = 0, fontHeight = 0, codeY = 0;  
        int red = 0, green = 0, blue = 0;  
  
        x = width / (codeCount + 2);//每个字符的宽度(左右各空出一个字符)  
        fontHeight = height - 2;//字体的高度  
        codeY = height - 4;  
  
        // 图像buffer  
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
        Graphics2D g = buffImg.createGraphics();        
          
        /*// 将图像背景填充为白色  
        g.setColor(Color.WHITE);  
        g.fillRect(0, 0, width, height);*/
        // 增加下面代码使得背景透明 
        buffImg = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);  
        g.dispose();  
        g = buffImg.createGraphics();  
        // 背景透明代码结束  
          
        // 画图BasicStroke是JDK中提供的一个基本的画笔类,我们对他设置画笔的粗细,就可以在drawPanel上任意画出自己想要的图形了。  
        g.setColor(new Color(255, 0, 0));  
        g.setStroke(new BasicStroke(1f));  
        g.fillRect(128, 128, width, height);
        
        // 生成随机数  
        Random random = new Random();    
                        //设置字体类型、字体大小、字体样式 
        Font font = new Font("微软雅黑",Font.PLAIN, fontHeight);
        g.setFont(font);  
        for (int i = 0; i < lineCount; i++) {  
            // 设置随机开始和结束坐标  
            int xs = random.nextInt(width);//x坐标开始  
            int ys = random.nextInt(height);//y坐标开始  
            int xe = xs + random.nextInt(width / 8);//x坐标结束  
            int ye = ys + random.nextInt(height / 8);//y坐标结束  
            // 产生随机的颜色值,让输出的每个干扰线的颜色值都将不同。  
            red = random.nextInt(255);  
            green = random.nextInt(255);  
            blue = random.nextInt(255);  
            g.setColor(new Color(red, green, blue));  
            g.drawLine(xs, ys, xe, ye);  
        }  
        // randomCode记录随机产生的验证码  
        StringBuffer randomCode = new StringBuffer();  
        // 随机产生codeCount个字符的验证码。  
        for (int i = 0; i < codeCount; i++) {  
            String strRand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);  
            // 产生随机的颜色值,让输出的每个字符的颜色值都将不同。  
            red = random.nextInt(255);  
            green = random.nextInt(255);  
            blue = random.nextInt(255);  
            //指定某种颜色
            //g.setColor(new Color(252, 145, 83));
            g.setColor(new Color(red, green, blue));  
            g.drawString(strRand, (i + 1) * x, codeY);  
            // 将产生的四个随机数组合在一起。  
            randomCode.append(strRand);  
        }  
        // 将四位数字的验证码保存到Session中。  
        code = randomCode.toString();  
    }  
    public void write(String path) throws IOException {  
        OutputStream sos = new FileOutputStream(path);  
        this.write(sos);  
    }  
    public void write(OutputStream sos) throws IOException {  
        ImageIO.write(buffImg, "png", sos);  
        sos.close();  
    }  
    public BufferedImage getBuffImg() {  
        return buffImg;  
    }  
    public String getCode() {  
        return code;  
    }  
    /** 
     * 测试函数,默认生成到d盘 
     * @param args 
     */  
    public static void main(String[] args) {  
        ValidateCode vCode = new ValidateCode(160,40,5,150);  
        try {  
            String path="D:/"+new Date().getTime()+".png";  
            System.out.println(vCode.getCode()+" >"+path);  
            vCode.write(path);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

2.2.控制层代码:

package com.dzqc.dz.common.controller;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dzqc.dz.common.util.MyAjaxResult;
@Controller
@RequestMapping("/test")
public class TestControllers {
    /**
     * 跳转页面
     * @param session
     * @param id
     * @return
     */
    @RequestMapping("/login")
    public String login() {
        return "loginTest";
    }
    
    /**
     * 获取验证码图片
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/user/check")
    public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {  
        // 通知浏览器不要缓存  
        response.setHeader("Expires", "-1");  
        response.setHeader("Cache-Control", "no-cache");  
        response.setHeader("Pragma", "-1");  
        ValidateCode vCode = new ValidateCode(160,40,5,150);
        // 将验证码输入到session中,用来验证  
        String code=vCode.getCode();
        request.getSession().setAttribute("code", code);  
        // 输出到web页面  
        ImageIO.write(vCode.getBuffImg(), "jpg", response.getOutputStream()); 
    }
    
    @RequestMapping("/submit")
    @ResponseBody
    public MyAjaxResult submit(HttpSession session,String username,String password,String judge) {
    	if(username==null||"".equals(username)) {
    		return MyAjaxResult.fail_300("请输入用户名");
    	}
    	if(password==null||"".equals(password)) {
    		return MyAjaxResult.fail_300("请输入密码");
    	}
    	if(judge==null||"".equals(judge)) {
    		return MyAjaxResult.success("请输入验证码");
    	}
    	Object code=session.getAttribute("code");
    	if(code==null) {
    		return MyAjaxResult.fail_300("验证码错误,请刷新验证码");
    	}else {
    		if(!judge.equals(code.toString())) {
    			session.removeAttribute("code");
    			return MyAjaxResult.fail_500("验证码错误");
    		}
    	}
    	session.removeAttribute("code");
    	return MyAjaxResult.success("登陆成功");
    }
}

3.jsp页面

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>login test</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
</head>
<body>
	用户名<input type="text" value="" name="username" id="username"><br>
	密码<input type="password" value="" name="password" id="password"><br><br>
	<img alt="验证码" src="${path}/test/user/check" id="img"><br><br>
	验证码<input type="text" value="" name="judge" id="judge"><br>
	<input type="button" value="提交" id="sub"><br>
	<script type="text/javascript">
		$(function(){
			$("#img").click(function(){
				var url = "${path}/test/user/check?number="+Math.random();  
			    $("#img").attr("src",url);
			})
			$("#sub").click(function(){
				$.ajax({
					url:'${path}/test/submit',
					dataType:'json',
					type:'post',
					data:{
						username:$("#username").val(),
						password:$("#password").val(),
						judge:$("#judge").val()
					},
					success:function(res){
						alert(res.msg)
						if(res.code==500){
							var url = "${path}/test/user/check?number="+Math.random();  
						    $("#img").attr("src",url);
						}
					},
					error:function(res){
						alert("网络错误");
					}
				})
			})
		})
	</script>
</body>
</html>





评论区
请写下您的评论...
暂无评论...
猜你喜欢
框架 1284 /groupIdartifactIdkaptcha/artifactIdversion${kaptcha.version}/version/dependency生成的配置类importcom.google
工具 1839 java正则表达式同时手机号或电话号importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassPhone
工具 2645 /versionclassifierjdk15/classifier/dependencydependency groupIdcom.aliyun/groupId artifactIdaliyun-java-sdk-core/
工具 2451 packagecom.dzqc.dz.main.util;importjava.util.regex.Matcher;importjava.util.regex.Pattern;/***
工具 1677 工具类packagecom.dzqc.yx.util;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importsun.misc.BASE64Decoder;impo
数据结构与算法 2352 java实现五子棋人机对战packagefir;importjava.awt.*;importjavax.swing.JPanel;/***有背景的Panel类*@authortntxia
其他 1054 式:Word,Excel,PowerPoint,Project,等office文档以及PDF文档。除了强大的文件操纵组件之外,Aspose.Total还提供了用于制、写电子邮件、拼写检查、创建条形
weblog 5441 前言之前的博客中提到了floyd最短路径算法,此算法的优点是,简单易懂,核心算法代只有5行,但是缺点是时间复杂度o(n3),时间复杂度太高。而下面要介绍的Dijkstra算法虽然设计上略有复杂,但
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1 2024-08  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript 加密算法
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。