[Quick Start Series] Get started quickly with the creation of verification codes (ValidateCode) for login and the old-fashioned verification codes that come with Javaweb

[Quick Start Series] Get started quickly with the creation of verification codes (ValidateCode) for login and the old-fashioned verification codes that come with Javaweb

verification code

Introduction

CAPTCHA is the abbreviation of "Completely Automated Public Turing test to tell Computers and Humans Apart" (Turing Test to Tell Computers and Humans Apart), which is a public fully automatic program to distinguish whether the user is a computer or a human. A commonly used CAPTCHA test is to allow users to input text or numbers displayed on a distorted picture. The distortion is to avoid being automatically recognized by computer programs such as Optical Character Recognition (OCR, Optical Character Recognition). Text loses its effect. For the physically and mentally disabled who cannot see the image, the alternative method is to use voice to read the alphanumerics. In order to prevent voice recognition from analyzing the voice, the content of the voice will have noise.

effect

  • Prevent batch registration, ticket swiping, forum flooding, and page swiping.
  • Effectively prevent a hacker from making continuous login attempts to a specific registered user with a specific program brute force cracking method.
  • The verification code is usually composed of some lines and some irregular characters, and its main function is to prevent some hackers from stealing the password data.

common verification code

  1. The traditional input verification code
    is mainly verified by the user inputting letters, numbers, Chinese characters, etc. in the picture.
    Representative: Most websites use this form of verification.
    Features: Simple and easy to operate, good human-computer interaction. But the safety factor is low and it is easy to be cracked.
  2. The input-type graphic verification code
    has exquisite patterns, and the recognition text is also clear and recognizable, focusing on advertising.
    Representative: Solve Media, Yuchu Verification Code
    Features: It is not so much a verification code as it is an advertising space.
  3. Pure Behavior Verification Code
    Slide the optional fragments to the correct position in a straight line as required
    Representative: Extreme Verification Code
    Features: Simple operation and good experience. Single dimension, easy to be reverse simulated, incompatible with mobile page switching.
  4. Icon selection and behavior assistance
    Given a set of pictures, click one or more of them as required. Borrow the difficulty of recognizing everything to block the machine.
    Representative: touch verification code, Google new verification code, 12306 verification code
    Features: strong security. For pictures, galleries, and technical requirements are high.
  5. Click-based graphic verification and behavior assistance
    Remind users to click the same word in the picture for verification through text.
    Representative: Taobao new verification code, touch verification code
    Features: simple operation, good experience, large single picture area, difficult to crack.
  6. Smart verification code
    Through behavioral characteristics, device fingerprints, data risk control and other technologies, normal users are exempted from verification, and abnormal users are forced to verify
    Representative: Touch Smart Verification Code
    Features: Simple and convenient, distinguish between human and machine, human and human, equipment and equipment.

Specific use

Servlet version

step

1. Import the jar package to your web project

ValidateCode.jar

maven dependencies:

<!-- ValidateCode验证码 -->
<dependency>
    <groupId>cn.dsna</groupId>
    <artifactId>ValidateCode</artifactId>
    <version>1.0.0</version>
</dependency>

2. One more configuration in the encoding filter (to prevent garbled characters)

//设置图像编码集
response.setContentType("image/jpeg;charset=utf-8");

3. Configure the verification code Servlet file ValidateCodeServlet.java

@WebServlet("/ValidateCodeServlet")
public class ValidateCodeServlet extends HttpServlet {
    
    
	private static final long serialVersionUID = 1L;
       

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
				
		//四个参数:验证码宽度、验证码高度、验证码有几位,验证码有几个干扰项
		ValidateCode validateCode = new ValidateCode(110,26,4,10);
		String code = validateCode.getCode();
		System.out.println(code);
        //在这一步存入code值(就是图片中验证码的字母和数字),用于一会在登录Servlet中接收进行判断用户输入的验证码是否和图片中的验证码一致
		request.getSession().setAttribute("code", code);
		//图片响应给客户端
		validateCode.write(response.getOutputStream());

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		doGet(request, response);
	}

}

If you directly access this Servlet page, you can see the verification code picture that will be displayed:

Please add a picture description

4. Configure the front-end jsp page (html is fine, just look at it)

<!-- 配置cookie(html不用这) -->
<%
String ucode = "";
String upwd = "";
//用request获取cookie
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length != 0) {
    for (Cookie cookie : cookies) {
        if (cookie.getName().equals("usercode")) {
            //获得cookie值
            ucode = cookie.getValue();
            //如果其值存在中文,就将其解码
            ucode = URLDecoder.decode(ucode,"utf-8");
        }
        if (cookie.getName().equals("upwd")) {
            //获得cookie值
            upwd = cookie.getValue();
        }

    }
}
%>


<!-- html代码(value不用要) -->
<!-- 用value设置cookie默认值 -->
账号:<input type="text" id="usercode" name="ucode" value="<%=ucode%>"/><br/>	
密码:<input type="text" id="userpwd" name="upwd" value="<%=upwd%>"/><br/>

<!-- 这里是验证码 -->
验证码:<input name="validatecode" id="validatecode" placeholder="验证码" type="text">
<a href="javascript:fn1()" style="text-decoration:none;">看不清,换一张<br/><img id="imageCode" src="/web08/ValidateCodeServlet(访问验证码Servlet的路径)" /></a>
<br/><br/>
<input type="button" id="loginbtn" value="提交"/>

js code (I wrote it all together, just write it separately to stick to what you need):

<script type="text/javascript" src="js/jquery-3.6.0.js" charset="UTF-8"></script>
<script type="text/javascript">
	
//改变验证码
function fn1(){
    
    
	//随便一个参数或者随机数,使图片转换	(可能因为验证码缓存所以不设置的话只能换一次)
	var d = new Date();	//(因为日期时间比较唯一)
	document.getElementById("imageCode").src = "/web08/ValidateCodeServlet?t="+d.getTime();
	
}

	//登录的点击事件:
	$(function(){
    
    
				
		$("#loginbtn").click(function(){
    
    
			//通过id得到值
			 var usercode = $("#usercode").val();
			 var userpwd = $("#userpwd").val();
			 var validatecode = $("#validatecode").val();
			 $.get("LoginServlet",
					 {
    
    usercode:usercode,userpwd:userpwd,validatecode:validatecode},
					 function(res){
    
    
						 alert(res.msg);  //判断登录对错状态
						 if(res.code==1){
    
    
							 location = "/web08/web/ProviderAllServlet(跳到成功登录后的页面)"
						 }else {
    
    
							 location = "/web08/login.jsp(原地刷新)"
						 }
					 },
					 "json");
		});
	});


</script>

The front-end effect after writing:

Please add a picture description

Then configure the login Servlet in your own project (I am LoginServlet.ava here):

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    
    
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginServlet() {
    
    
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		String json=null;
		//设置网页字符编码集
        response.setContentType("text/html;charset=utf-8");
        
        //设置接收参数
        String ucode = request.getParameter("usercode");
        String upwd = request.getParameter("userpwd");
        String validatecode = request.getParameter("validatecode");
        //登录方法
      	UserService us = new UserServiceImpl();
      	User user = new User();
      	user = us.login(ucode, upwd);
      	//1、看验证码是否为null或是空字符串,如果不是进行下一步判断
      	if(validatecode == null || validatecode.equals("")) {
    
    
			json = "{\"code\":2,\"msg\":\"验证码不能为空!!\"}";
		}else {
    
    
            //2、拿取当时从验证码Servlet中得到的code(也就是验证码信息),然后与用户输入的验证码进行比较,若比较成功则进行下一步用户登录验证的判断,否则返回验证码错误的信息
			String code = (String)request.getSession().getAttribute("code");
            //忽略大小写进行比较
			if(validatecode.equalsIgnoreCase(code)) {
    
    
                //3、比较相等后,开始写登录的业务判断
				if(user != null) {
    
    
					String uname = user.getUserName();
					request.setAttribute("ucode",ucode);
					request.setAttribute("uname",uname);
					//设置Cookie
					//如果Cookie中值存在中文,就将其编码设置成utf-8(也可能因为设置了反而乱码,看具体情况)
					String usercode = URLEncoder.encode(ucode, "utf-8");
					Cookie cookie = new Cookie("usercode",usercode);
					//设置路径为根目录(方便使用)
					cookie.setPath("/");
					//设置cookie生命周期
					cookie.setMaxAge(20);	//s
					//添加cookie(response)
					response.addCookie(cookie);
					
					Cookie cookie1 = new Cookie("upwd",upwd);
					//设置路径为根目录(方便使用)
					cookie1.setPath("/");
					//设置cookie生命周期
					cookie1.setMaxAge(20);	//s
					//添加cookie(response)
					response.addCookie(cookie1);
					
					//创建session
					HttpSession session = request.getSession();
					//存入用户session
					session.setAttribute("uname", uname);
					//设置session过期时间
					session.setMaxInactiveInterval(60 * 60);
					
					json = "{\"code\":1,\"msg\":\"登录成功\"}";
					//response.sendRedirect("web/ProviderAllServlet");
				} else {
    
    
					json = "{\"code\":2,\"msg\":\"登录失败\"}";
					//response.sendRedirect("/login.jsp");
				}
			}else {
    
    
				json = "{\"code\":2,\"msg\":\"验证码错误!!\"}";
			}
		}
		//回应控制台输出:
		PrintWriter out = response.getWriter();
		out.print(json);
		System.out.println(json);
	}
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

That's it

Another Old Fashioned Captcha

The verification code that comes with java.awt is used, which is very troublesome. You need to draw a verification code step by step, but some features can be customized:

package com.r.servlet;

import java.io.IOException;
import java.util.Random;

import java.awt.image.BufferedImage;
import java.awt.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * 验证码
 * @author
 *
 */

@WebServlet("/ValidateCodeServlet2")
public class ValidateCodeServlet2 extends HttpServlet {
    
    
	private static final long serialVersionUID = 1L;
       
	private void codeChange(HttpServletResponse response) throws IOException{
    
    
		int width=120;
		int height=27;
		/**
		 * 1.在内存中创建一个图像对象
		 */
		//构造一个类型为预定义图像类型之一的 BufferedImage。
		//表示一个具有 8 位 RGB 颜色分量的图像,对应于 Windows 或 Solaris 风格的 BGR 颜色模型,具有打包为整数像素的 Blue、Green 和 Red 三种颜色。			
		BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
																							
		//创建一个画笔
		Graphics g=img.getGraphics(); 
		
		//给背景图片添加一个颜色
		g.setColor(Color.ORANGE);
		g.fillRect(1, 1, width-2, width-2);//建议使用IE浏览器访问,Google浏览器和获取均显示为居中的图片,ie显示左上角
		
		//给边框一个色
		g.setColor(Color.GREEN);
		g.drawRect(0, 0, width-1, height-1);
		
		//设置文本样式
		Random rr = new Random();
		g.setColor(Color.BLACK);
		g.setFont(new Font("宋体",Font.BOLD|Font.ITALIC,15));//Font对象 ----根据指定名称、样式和磅值大小,创建一个新 Font。
		g.setColor(new Color(rr.nextInt(255),rr.nextInt(255),rr.nextInt(255)));  //设置颜色,它的红,绿,蓝都在0~255之间随机
		
		//给图片添加文本
		Random rand=new Random();
		int position=20;
		for(int i=0;i<4;i++){
    
    
			g.drawString(rand.nextInt(10)+"", position, 20);//给图片填充文本
			position+=20;
		}
		
		//给图片加噪点
		for(int i=0;i<20;i++){
    
    
            Random r = new Random();
            int x = r.nextInt(width);
            int y = r.nextInt(height);
            g.drawOval(x,y,5,5);
        }


		//将图片以对象流的方式输出到客户端
		ImageIO.write(img, "jpg", response.getOutputStream());
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

		codeChange(response);

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		doGet(request, response);
	}

}

This is the effect:

Please add a picture description

You can also change the color of each character

package com.r.servlet;

import java.io.IOException;
import java.util.Random;

import java.awt.image.BufferedImage;
import java.awt.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ValidateCodeServlet3
 */
@WebServlet("/ValidateCodeServlet3")
public class ValidateCodeServlet3 extends HttpServlet {
    
    
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ValidateCodeServlet3() {
    
    
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        doPost(req, resp);
      }
      //图片的高度,宽度,文本的个数
      private static final int IMG_HEIGHT = 30;
      private static final int IMG_WIDTH = 100;
      private static final int IMG_NUM = 4;
      @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //1.设置响应头,图片的缓存
        resp.setHeader("Pragma", "no-cache");
        resp.setHeader("Cache-Control", "no-cache");
        //设置响应的内容类型,MIME TYPE
        resp.setContentType("image/jpeg");
        //创建绘制图片的缓存流,BufferedImage.TYPE_INT_RGB图片为三原色图片
        BufferedImage bi = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB);
        //获取画笔对象
        Graphics g = bi.getGraphics();
        //设置画笔的颜色
        g.setColor(new Color(100,230,200));
        //绘制图片的背景色
        g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
        //验证码中使用字符
        char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
        //创建随机数
        Random random = new Random();
        //创建StringBuffer存储随机字符
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < IMG_NUM; i++) {
    
    
          //生成随机数
          int index = random.nextInt(chars.length);
          //取出随机字符
          char randomChar = chars[index];
          //设置画笔颜色
          g.setColor(new Color(random.nextInt(150),random.nextInt(200),random.nextInt(255)));
          //设置文本字体
          g.setFont(new Font("Arial",Font.PLAIN,18));
	       //给图片加噪点
	  	   for(int j=0;j<7;j++){
    
    
	          Random r = new Random();
	          int x = r.nextInt(IMG_WIDTH);
	          int y = r.nextInt(IMG_HEIGHT);
	          g.drawOval(x,y,5,5);
	       }
          //将字符绘制到图片上
          g.drawString(String.valueOf(randomChar), 15+(i*20), 20);
          //将随机字符放入StringBuffer中
          buffer.append(randomChar);
        }
        //将存储随机字符的String对象放入Session中
        req.getSession().setAttribute("validateCode", buffer.toString());
        //通过ImageIo流,将图片输出到页面中
        ImageIO.write(bi, "jpg", resp.getOutputStream());
      }
}

Effect:

Please add a picture description

Guess you like

Origin blog.csdn.net/weixin_55452293/article/details/127921272