零碎 验证码
每篇一语:zero-broken 零碎。中文“直译”英文,虽然不符合语法,但生命在于“创造”!
1.生成验证码
2.页面中获得验证码
3.提交时验证
====================== 华丽丽的分割线 ======================
1.生成验证码
1.1. 生成验证码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.awt.Color;
2 import java.awt.Font;
3 import java.awt.Graphics;
4 import java.awt.image.BufferedImage;
5 import java.util.Random;
6
7 public class CheckCode {
8
9 private static Color getRandColor(int fc, int bc) {
10 Random random = new Random();
11 if (fc > 255)
12 fc = 255;
13 if (bc > 255)
14 bc = 255;
15 int r = fc + random.nextInt(bc - fc);
16 int g = fc + random.nextInt(bc - fc);
17 int b = fc + random.nextInt(bc - fc);
18 return new Color(r, g, b);
19 }
20
21 public static BufferedImage getImage(StringBuffer sb){
22
23 // 验证码宽度和高度
24 int width = 80, height = 30;
25 // 验证码字体大小
26 int fontSize = height;
27 // 验证码位数
28 int code = 4;
29
30 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
31
32 // 获取绘画对象
33 Graphics g = image.getGraphics();
34 // 设定背景色
35 g.setColor(getRandColor(165, 200));
36 g.fillRect(0, 0, width, height);
37 // 设定字体
38 g.setFont(new Font("Times New Roman", Font.BOLD, fontSize));
39
40 // 随机产生干扰线,使图象中的验证码不易被其它程序探测到
41 Random random = new Random();
42 g.setColor(getRandColor(100, 125));
43 for (int i = 0; i < 85; i++) {
44 int x = random.nextInt(width);
45 int y = random.nextInt(height);
46 int xl = random.nextInt(12);
47 int yl = random.nextInt(12);
48 g.drawLine(x, y, x + xl, y + yl);
49 }
50
51 // 取随机产生的验证码
52 for (int i = 0; i < code; i++) {
53 String rand = String.valueOf(random.nextInt(10));
54 sb.append(rand);
55
56 // 将验证码显示到图象中
57 g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
58 // 生成随机数,能根据验证图片大小控制验证码间距,但做得还不够好
59 g.drawString(rand, width*(i+1)/(code+2), height-(height/10));
60 }
61
62 // 图象生效
63 g.dispose();
64 return image;
65 }
66 }
附注:该验证码做得不够漂亮,验证码的间距控制可以进一步去完美,参数也应该抽出。
1.2 定义获得验证码的Action:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.awt.image.BufferedImage;
2 import java.io.IOException;
3 import java.io.OutputStream;
4
5 import javax.imageio.ImageIO;
6 import javax.servlet.http.HttpServletResponse;
7 import javax.servlet.http.HttpSession;
8
9 /**
10 * 验证码
11 */
12
13 public class NoParameterAction {
14
15 public void getCheckcode(){
16 OutputStream out = null;
17 try {
18 StringBuffer sRand = new StringBuffer();
19 BufferedImage image = CheckCode.getImage(sRand);
20 // 将认证码存入SESSION
21 HttpSession session = MyServletContext.getSession();
22 session.setAttribute("code", sRand);
23
24 HttpServletResponse response = MyServletContext.getResponse();
25 // 设置页面不缓存
26 response.setHeader("Pragma", "No-cache");
27 response.setHeader("Cache-Control", "no-cache");
28 response.setContentType("image/jpeg;charset=utf8");
29 response.setDateHeader("Expires", 0);
30 out = response.getOutputStream();
31
32 // 输出图象到页面
33 ImageIO.write(image, "JPEG", out);
34 } catch (IOException e) {
35 System.out.println("验证码输出异常1");
36 } catch(Exception e){
37 System.out.println("验证码输出异常2");
38 } finally{
39 if(out != null){
40 try {
41 out.close();
42 } catch (IOException e) {
43 System.out.println("验证码输出异常");
44 }
45 }
46 }
47 }
48 }
附注:关于MyServletContext是自己写的一个类,仅仅是方便而已,该类见本页面最下(当然,也可用 ServletActionContext.getRequest().getSession();)
1.3 将Action 配置到 struts.xml:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
4 "http://struts.apache.org/dtds/struts-2.1.dtd">
5
6 <struts>
7 <include file="struts-default.xml"></include>
8 <constant name="struts.multipart.maxSize" value="1024288000" />
9
10 <package name="test" namespace="/" extends="struts-default">
11
12 <!-- 此处略去 -->
13
14 <!-- 验证码 -->
15 <action name="checkcode" class="com.test.NoParameterAction" method="getCheckcode" />
16
17 <!-- 此处略去 -->
18
19 </package>
20 </struts>
====================== 华丽丽的分割线 ======================
2.页面中获得验证码
2.1. 页面中获得验证码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <%@ page language="java" pageEncoding="UTF-8"%>
2 <%
3 String path = request.getContextPath();
4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
5 %>
6
7 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
8 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
9
10 <html xmlns="http://www.w3.org/1999/xhtml">
11 <head>
12 <title>验证码测试页面</title>
13 </head>
14
15 <body>
16 <div id="checkcode_div">
17 <label style="vertical-align:middle;">验证码:</label><input style="vertical-align:middle;" type="text" id="checkcode" name="checkcode" maxlength="4" class="textfield" />
18 <img id="checkcode_img" style="vertical-align:middle;" src="<%=basePath %>/checkcode" width="80px" height="30px" title="点击更换验证码" onclick="javascript:this.src='<%=basePath %>/checkcode?m='+new Date()" />
19 <div id="error_checkcode" style="margin-top:5px;"></div>
20 </div>
21 </body>
22
23 </html>
2.2 零碎之关于点击获得验证码:
前面生成验证码时设置了不缓存,但还不够,还得实现每次点击立刻更新图片,故得在<img>标签中更改路径,这才会使得每次点击后图片立刻更换。所以,每次触发点击事件时,在发出请求加个时间参数,以便消除缓存。
====================== 华丽丽的分割线 ======================
3.提交时验证
3.1 提交时验证
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class TestCheckCode {
2
3 // 验证验证码是否正确
4 public boolean checkCode(String code) {
5 if(code != null && MyServletContext.getSession().getAttribute("code").toString().equals(code.trim())) {
6 return true;
7 }
8 return false;
9 }
10 }
附注:关于MyServletContext是自己写的一个类,仅仅是方便而已,该类见本页面最下(当然,也可用 ServletActionContext.getRequest().getSession().getAttribute("code");)
3.2 零碎之关于提交时验证
提交时,服务端先判断验证码,若验证码错误,则接下来的一系列验证就不必判断。
====================== 华丽丽的分割线 ======================
附注:MyServletContext
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import javax.servlet.http.HttpServletRequest;
2 import javax.servlet.http.HttpServletResponse;
3 import javax.servlet.http.HttpSession;
4
5 import org.apache.struts2.ServletActionContext;
6
7 public class MyServletContext {
8 public static HttpServletRequest getRequest(){
9 return ServletActionContext.getRequest();
10 }
11
12 public static HttpServletResponse getResponse(){
13 HttpServletResponse response = ServletActionContext.getResponse();
14 response.setCharacterEncoding("UTF-8");
15 response.setHeader("Pragma", "no-cache");
16 response.setHeader("Cache-Control","no-cache");
17 response.setContentType("text/html;charset=UTF-8");
18 return response;
19 }
20
21 public static HttpSession getSession(){
22 return getRequest().getSession();
23 }
24 }