Java生成验证码简记

验证码定义

验证码(captcha):是一种区分用户是计算机还是人的公共全自动程序。

作用:可以防止恶意破解密码、刷票、灌水,有效防止对某一个特定注册用户用特定程序进行暴力破解的登录尝试。

验证码交互逻辑

生成

  1. 生成随机的验证码字符capText和对应的图片capImage
  2. 生成随机的关键字r
  3. 将r和capText组成键值对存入缓存(如Redis)
  4. 将固定字符code和r组成键值对存入Session或Cookie中
  5. 将验证码图片capImage数据返回前端

验证

  1. 根据固定字符code获取缓存关键字r
  2. 根据r从缓存中读取验证码字符capText
  3. 将capText和用户提交的验证码进行比较,判断结果

验证码简单实现

验证码生成Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 验证码生成Servlet
*/
public class ImageServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
BufferedImage bi=new BufferedImage(68,22,BufferedImage.TYPE_INT_BGR);
Graphics g=bi.getGraphics();
Color c=new Color(250,150,255);
g.setColor(c);
g.fillRect(0,0,68,22);
//验证码字符集合
char[] ch="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
Random r=new Random();
int len=ch.length;
int index;
StringBuilder sb=new StringBuilder();
for(int i=0;i<4;++i){
index=r.nextInt(len);
//设置验证码字符随机颜色
g.setColor(new Color(r.nextInt(88),r.nextInt(188),r.nextInt(255)));
//画出对应随机的验证码字符
g.drawString(ch[index]+"",(i*15)+3,18);
sb.append(ch[index]);
}
//把验证码字符串放入Session
request.getSession().setAttribute("piccode", sb.toString());
//在HttpServletResponse中写入验证码图片信息
ImageIO.write(bi, "JPG", response.getOutputStream());
}
}

前端页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page contentType="text/html;charset=GBK" language="java" import="java.util.*" pageEncoding="gbk" %>
<html>
<head>
<script type="text/javascript">
function reloadCode() {
console.log("reload");
var time = new Date().getTime();
document.getElementById("imagecode").src = "<%=request.getContextPath()%>/servlet/ImageServlet?d=" + time;
}
</script>
</head>
<body>
<form action="<%=request.getContextPath()%>/servlet/LoginServlet" method="get">
<h2>Java验证码测试</h2>
验证码:<input type="text" name="checkcode"/>
<img alt="验证码" id="imagecode" src="<%=request.getContextPath()%>/servlet/ImageServlet"/>
<a href="javascript:reloadCode();">看不清楚</a>
<br/>
<input type="submit" value="提交"/>
</form>
<br/>
</body>
</html>

登录验证Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 登录验证Servlet
*/
public class LoginServlet extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String piccode=(String)request.getSession().getAttribute("piccode");
String checkcode=request.getParameter("checkcode");
response.setContentType("text/html;charset=gbk");
PrintWriter out=response.getWriter();
if(checkcode.equalsIgnoreCase(piccode)){
out.println("正确");
}else{
out.println("错误");
}
out.flush();
out.close();
}
}

Web配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<web-app>
<display-name>Java Check Code</display-name>
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>com.checkcode.ImageServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.checkcode.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/servlet/ImageServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

测试结果 测试结果