Servlet仿CSDN动态验证码的生成-带数字和字母
一、实现的思路:
(1)首先,需要创建一个Servlet。该Servlet通过字节型响应给客户端返回一个图片,该图片是通过JDK中Java 2D的类库来生成一个图片。图片的生成是依靠一个随机数来完成,然后将这个随机数写成图片格式。最后在Session将这个随机的字符串的状态保持住,以便在用户填写后进行对比。
(2)其次,在需要加入验证码的JSP页面中,通过<img src="生成验证码图片的URI"/>引入该图片。
(3)最后,单用户填写完验证码后,提交到某一个Servlet中。在这个Servlet中,通过request.getParameter()方法获取用户添加的验证码,然后取出后与Session中生成的验证码进行对比,如果对比成功就表示通过,否则返回该页面给用户提示验证码错误的信息。
(4)然后如果要仿CSDN动态验证码,就要分别生成数字和符号(+,-,*),根据符号,计算结果,计算中文,把结果存储到一个List<String>中去。
先来看看效果:
二、代码
这里首先实现只有数字和字母的,还不带符号运算
1、工程整体结构
2、生成带数字和图片的代码
AuthCode.java
- package com.mucfc;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Font;
- import java.awt.image.BufferedImage;
- import java.util.Random;
- /**
- * 生成验证码图片
- * @author 林炳文Evankaka(博客:http://blog.csdn.net/evankaka)
- * @since 2015.6.22
- */
- public class AuthCode {
- public static final int AUTHCODE_LENGTH = 5; // 验证码长度
- public static final int SINGLECODE_WIDTH = 15; // 单个验证码宽度
- public static final int SINGLECODE_HEIGHT = 30; // 单个验证码高度
- public static final int SINGLECODE_GAP = 4; // 单个验证码之间间隔
- public static final int IMG_WIDTH = AUTHCODE_LENGTH * (SINGLECODE_WIDTH + SINGLECODE_GAP);
- public static final int IMG_HEIGHT = SINGLECODE_HEIGHT;
- public static final char[] CHARS = {'0','1', '2', '3', '4', '5', '6', '7', '8',
- '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
- static Random random = new Random();
- /**
- * 返回图片中的数字
- * @return String
- */
- public static String getAuthCode() {
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < 5; i++) {// 生成6个字符
- buffer.append(CHARS[random.nextInt(CHARS.length)]);
- }
- return buffer.toString();
- }
- /**
- * 返回带数字的图片
- * @return BufferedImage
- */
- public static BufferedImage getAuthImg(String authCode) {
- // 设置图片的高、宽、类型
- // RGB编码:red、green、blue
- BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT,
- BufferedImage.TYPE_INT_BGR);
- // 得到图片上的一个画笔
- Graphics g = img.getGraphics();
- // 设置画笔的颜色,用来做背景色
- g.setColor(Color.RED);
- // 用画笔来填充一个矩形,矩形的左上角坐标,宽,高
- g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
- // 将画笔颜色设置为黑色,用来写字
- g.setColor(Color.BLACK);
- // 设置字体:宋体、不带格式的、字号
- g.setFont(new Font("宋体", Font.PLAIN, SINGLECODE_HEIGHT + 5));
- // 输出数字
- char c;
- for (int i = 0; i < authCode.toCharArray().length; i++) {
- // 取到对应位置的字符
- c = authCode.charAt(i);
- // 画出一个字符串:要画的内容,开始的位置,高度
- g.drawString(c + "", i * (SINGLECODE_WIDTH + SINGLECODE_GAP)
- + SINGLECODE_GAP / 2, IMG_HEIGHT);
- }
- Random random = new Random();
- // 干扰素
- for (int i = 0; i < 15; i++) {
- int x = random.nextInt(IMG_WIDTH);
- int y = random.nextInt(IMG_HEIGHT);
- int x2 = random.nextInt(IMG_WIDTH);
- int y2 = random.nextInt(IMG_HEIGHT);
- g.drawLine(x, y, x + x2, y + y2);
- }
- return img;
- }
- }
在这里还可以自己更改图片的背景色、验证码的个数、干扰素强度等,有兴趣的同学自己好好设置下吧
3、生成动态验证码的servlet
getAuthCodeServlet.java
- package com.mucfc;
- import java.io.IOException;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * 得到生成验证码图片的servlet
- * @author 林炳文Evankaka(博客:http://blog.csdn.net/evankaka)
- * @since 2015.6.22
- */
- public class getAuthCodeServlet extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String authCode = AuthCode.getAuthCode();
- request.getSession().setAttribute("authCode", authCode); //将验证码保存到session中,便于以后验证
- try {
- //发送图片
- ImageIO.write(AuthCode.getAuthImg(authCode), "JPEG", response.getOutputStream());
- } catch (IOException e){
- e.printStackTrace();
- }
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request,response);
- }
- }
4、index调用,并进行输入正确的判断
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css">
- -->
- </head>
- <body>
- <form action="index.jsp" method="post">
- <img src="servlet/GetAuthCodeServlet" id="authImg"/><a href="#" onClick="window.location.reload()">看不清</a><br>
- <input type="text" name="inputCode">
- <%
- String inputCode = (String)request.getParameter("inputCode");
- String authCode = (String)session.getAttribute("authCode");
- if(inputCode!=null){
- if(authCode.equalsIgnoreCase(inputCode)){
- out.print("验证码正确!");
- }else{
- out.print("验证码错误!请重新输入!");
- }
- }
- %>
- <br>
- <input type="submit" value="提交">
- </form>
- </body>
- </html>
这里在直接都在一个jsp中判断了
5、web.xml设置
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <servlet>
- <servlet-name>getAuthCodeServlet</servlet-name>
- <servlet-class>com.mucfc.getAuthCodeServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>getAuthCodeServlet</servlet-name>
- <url-pattern>/servlet/GetAuthCodeServlet</url-pattern>
- </servlet-mapping>
- <welcome-file-list>
- <welcome-file>index.html</welcome-file>
- <welcome-file>index.htm</welcome-file>
- <welcome-file>index.jsp</welcome-file>
- <welcome-file>default.html</welcome-file>
- <welcome-file>default.htm</welcome-file>
- <welcome-file>default.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
6、运行效果
三、仿CSDN动态验证码实现
整个工程结构不变,
1、AuthCode改成如下
- package com.mucfc;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Font;
- import java.awt.image.BufferedImage;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
- /**
- * 生成验证码图片
- * @author 林炳文Evankaka(博客:http://blog.csdn.net/evankaka)
- * @since 2015.6.22
- */
- public class AuthCode {
- public static final int AUTHCODE_LENGTH = 5; // 验证码长度
- public static final int SINGLECODE_WIDTH = 20; // 单个验证码宽度
- public static final int SINGLECODE_HEIGHT = 30; // 单个验证码高度
- public static final int SINGLECODE_GAP = 4; // 单个验证码之间间隔
- public static final int IMG_WIDTH = AUTHCODE_LENGTH * (SINGLECODE_WIDTH + SINGLECODE_GAP);
- public static final int IMG_HEIGHT = SINGLECODE_HEIGHT;
- public static final char[] CHARS = {'0','1', '2', '3', '4', '5', '6', '7', '8', '9' };
- public static final char[] OPERATION={'+','-','*'};
- static Random random = new Random();
- /**
- * 返回图片中的数字
- * @return String
- */
- public static List<String> getAuthCode() {
- char char1 = CHARS[random.nextInt(CHARS.length)];
- char char2 = CHARS[random.nextInt(CHARS.length)];
- char opt = OPERATION[random.nextInt(OPERATION.length)];
- StringBuffer buffer = new StringBuffer();
- buffer.append(char1);
- buffer.append(getOperation(opt));
- buffer.append(char2);
- String result=getResult(char1,char2,opt);
- List<String> list=new ArrayList<String>();
- list.add(buffer.toString());
- list.add(result);
- return list;
- }
- /**
- * 返回计算的结果
- * @param operation
- * @return String
- */
- public static String getResult(char char1,char char2,char operation){
- int int1 = Integer.parseInt(String.valueOf(char1));
- int int2 = Integer.parseInt(String.valueOf(char2));
- if('+'==operation)
- return String.valueOf(int1+int2);
- else if ('-'==operation)
- return String.valueOf(int1-int2);
- else if ('*'==operation)
- return String.valueOf(int1*int2);
- else
- return null;
- }
- /**
- * 返回符号对应的中文
- * @param operation
- * @return String
- */
- public static String getOperation(char operation){
- if('+'==operation)
- return "加上";
- else if ('-'==operation)
- return "减去";
- else if ('*'==operation)
- return "乘以";
- else
- return null;
- }
- /**
- * 返回带数字的图片
- * @return BufferedImage
- */
- public static BufferedImage getAuthImg(String authCode) {
- // 设置图片的高、宽、类型
- // RGB编码:red、green、blue
- BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT,
- BufferedImage.TYPE_INT_BGR);
- // 得到图片上的一个画笔
- Graphics g = img.getGraphics();
- // 设置画笔的颜色,用来做背景色
- g.setColor(Color.YELLOW);
- // 用画笔来填充一个矩形,矩形的左上角坐标,宽,高
- g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
- // 将画笔颜色设置为黑色,用来写字
- g.setColor(Color.BLACK);
- // 设置字体:宋体、不带格式的、字号
- g.setFont(new Font("宋体", Font.PLAIN, SINGLECODE_HEIGHT + 5));
- // 输出数字
- char c;
- for (int i = 0; i < authCode.toCharArray().length; i++) {
- // 取到对应位置的字符
- c = authCode.charAt(i);
- // 画出一个字符串:要画的内容,开始的位置,高度
- g.drawString(c + "", i * (SINGLECODE_WIDTH + SINGLECODE_GAP)
- + SINGLECODE_GAP / 2, IMG_HEIGHT);
- }
- Random random = new Random();
- // 干扰素
- for (int i = 0; i < 5; i++) {
- int x = random.nextInt(IMG_WIDTH);
- int y = random.nextInt(IMG_HEIGHT);
- int x2 = random.nextInt(IMG_WIDTH);
- int y2 = random.nextInt(IMG_HEIGHT);
- g.drawLine(x, y, x + x2, y + y2);
- }
- return img;
- }
- }
2、getAuthCodeServlet改成如下
- package com.mucfc;
- import java.io.IOException;
- import java.util.List;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * 得到生成验证码图片的servlet
- * @author 林炳文Evankaka(博客:http://blog.csdn.net/evankaka)
- * @since 2015.6.22
- */
- public class getAuthCodeServlet extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- List<String> list = AuthCode.getAuthCode();
- request.getSession().setAttribute("authCode", list.get(1)); //将验证码保存到session中,便于以后验证
- try {
- //发送图片
- ImageIO.write(AuthCode.getAuthImg(list.get(0)), "JPEG", response.getOutputStream());
- } catch (IOException e){
- e.printStackTrace();
- }
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request,response);
- }
- }
其它所有都不改变
运行后效果:
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
原文地址:http://blog.csdn.net/Evankaka/article/details/46597435
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)