服务器之家

服务器之家 > 正文

Spring框架生成图片验证码实例

时间:2020-06-07 12:20     来源/作者:daisy

这篇文章会从前台页面到后台实现完整的讲解,下面跟着小编一起来看看。

1、前台的代码,image.jsp

?
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>获取图片验证码</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/static/js/jquery-1.10.2.min.js"></script>
</head>
<body>
 
 <form action="##" method='post'>
   <input type="hidden" id="userId" name="userId" value="">
    <div class="form-group">
     <div class="email controls">
      <input type="text" name='loginName' id="loginName" placeholder="用户名" value="" class='form-control'/>
     </div>
    </div>
    <div class="form-group">
     <div class="pw controls">
      <input type="password" autocomplete="off" id="pwd" name="pwd" placeholder="密码" class='form-control'/>
     </div>
    </div>
 
    <div class="form-group">
     <div class="email controls">
      <input id="validateCode" onblur="checkImg(this.value)" name="validateCode" type="text" class="form-control" placeholder="输入验证码"/>
     </div>
     <span class="y_yzimg"><img id="codeValidateImg" onClick="javascript:flushValidateCode();"/></span>
     <p class="y_change"><a href="javascript:flushValidateCode();" >换一张</a></p>
    </div>
 
    <div class="form-group">
     <span class="text-danger"></span>
    </div>
 
    <div class="submit">
     <div class="remember">
 
        <input type="checkbox" name="remember" value="1" class='icheck-me' data-skin="square" data-color="blue" id="remember">
 
      <label for="remember">记住我</label>
     </div>
     <input type="button" value="登录" onclick="javascript:submitForm();" class='btn btn-primary'>
    </div>
   </form>
 
<script type="text/javascript">
$(document).ready(function() {
 flushValidateCode();//进入页面就刷新生成验证码
 });
 
/* 刷新生成验证码 */
function flushValidateCode(){
var validateImgObject = document.getElementById("codeValidateImg");
validateImgObject.src = "${pageContext.request.contextPath }/getSysManageLoginCode?time=" + new Date();
}
/*校验验证码输入是否正确*/
function checkImg(code){
 var url = "${pageContext.request.contextPath}/checkimagecode";
 $.get(url,{"validateCode":code},function(data){
 if(data=="ok"){
 alert("ok!")
 }else{
 alert("error!")
 flushValidateCode();
 }
 })
}
 
</script>
 
</body>
</html>

2、后台代码ImageGenController.java

?
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.dufyun.springmvc.web.controller;
 
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.dufy.javaweb.test.RandomValidateCode;
 
@Controller
public class ImageGenController {
 
 
 @RequestMapping(value="/toImg")
 public String toImg(){
 
  return "image/image";
 }
 
 
 //登录获取验证码
 @RequestMapping("/getSysManageLoginCode")
 @ResponseBody
 public String getSysManageLoginCode(HttpServletResponse response,
   HttpServletRequest request) {
  response.setContentType("image/jpeg");// 设置相应类型,告诉浏览器输出的内容为图片
  response.setHeader("Pragma", "No-cache");// 设置响应头信息,告诉浏览器不要缓存此内容
  response.setHeader("Cache-Control", "no-cache");
  response.setHeader("Set-Cookie", "name=value; HttpOnly");//设置HttpOnly属性,防止Xss攻击
  response.setDateHeader("Expire", 0);
  RandomValidateCode randomValidateCode = new RandomValidateCode();
  try {
   randomValidateCode.getRandcode(request, response,"imagecode");// 输出图片方法
  } catch (Exception e) {
   e.printStackTrace();
  }
  return "";
 }
 
 //验证码验证
 @RequestMapping(value = "/checkimagecode")
 @ResponseBody
 public String checkTcode(HttpServletRequest request,HttpServletResponse response) {
  String validateCode = request.getParameter("validateCode");
  String code = null;
  //1:获取cookie里面的验证码信息
  Cookie[] cookies = request.getCookies();
  for (Cookie cookie : cookies) {
   if ("imagecode".equals(cookie.getName())) {
    code = cookie.getValue();
    break;
   }
  }
  //1:获取session验证码的信息
  //String code1 = (String) request.getSession().getAttribute("");
  //2:判断验证码是否正确
  if(!StringUtils.isEmpty(validateCode) && validateCode.equals(code)){
   return "ok";
 
  }
  return "error";
  //这里我没有进行字母大小模糊的验证处理,感兴趣的你可以去试一下!
 }
 
}

3、生成验证码的工具类RandomValidateCode.java

?
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.dufy.javaweb.test;
 
 
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Random;
 
import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
public class RandomValidateCode {
 private Random random = new Random();
 private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";// 随机产生的字符串
 
 private int width = 80;// 图片宽
 private int height = 26;// 图片高
 private int lineSize = 40;// 干扰线数量
 private int stringNum = 4;// 随机产生字符数量
 
 /*
 * 获得字体
 */
 private Font getFont() {
  return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
 }
 
 /*
 * 获得颜色
 */
 private Color getRandColor(int fc, int bc) {
  if (fc > 255)
   fc = 255;
  if (bc > 255)
   bc = 255;
  int r = fc + random.nextInt(bc - fc - 16);
  int g = fc + random.nextInt(bc - fc - 14);
  int b = fc + random.nextInt(bc - fc - 18);
  return new Color(r, g, b);
 }
 
 /*
 * 绘制字符串
 */
 private String drowString(Graphics g, String randomString, int i) {
  g.setFont(getFont());
  g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
    .nextInt(121)));
  String rand = String.valueOf(getRandomString(random.nextInt(randString
    .length())));
  randomString += rand;
  g.translate(random.nextInt(3), random.nextInt(3));
  g.drawString(rand, 13 * i, 16);
  return randomString;
 }
 
 /*
 * 绘制干扰线
 */
 private void drowLine(Graphics g) {
  int x = random.nextInt(width);
  int y = random.nextInt(height);
  int xl = random.nextInt(13);
  int yl = random.nextInt(15);
  g.drawLine(x, y, x + xl, y + yl);
 }
 
 /*
 * 获取随机的字符
 */
 public String getRandomString(int num) {
  return String.valueOf(randString.charAt(num));
 }
 
 
 /**
 * 生成随机图片
 */
 public void getRandcode(HttpServletRequest request,HttpServletResponse response,String key) {
 
  // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
  BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_BGR);
  Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
  g.fillRect(0, 0, width, height);
  g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
  g.setColor(getRandColor(110, 133));
  // 绘制干扰线
  for (int i = 0; i <= lineSize; i++) {
   drowLine(g);
  }
  // 绘制随机字符
  String randomString = "";
  for (int i = 1; i <= stringNum; i++) {
   randomString = drowString(g, randomString, i);
  }
  //1:将随机生成的验证码放入Cookie中
  Cookie cookie = new Cookie(key,randomString);
  response.addCookie(cookie);
  //2:将随机生成的验证码放入session中
  String sessionid = request.getSession().getId();
  request.getSession().setAttribute(sessionid+key, randomString);
  System.out.println("*************" + randomString);
 
  //总结:这两种方式都是很好,
  //(1):使用cookie的方式,将验证码发送到前台浏览器,不安全!不建议使用。
  //(2):使用session的方式,虽然能解决验证码不发送到浏览器,安全性较高了,但是如果用户量太大,这样的存储方式会对服务器造成压力,影响服务器的性能。不建议使用。
  //这里暂时实现用这种方式,好的办法是,在项目中使用的缓存,将生成的验证码存放到缓存中,设置失效时间,这样既可以实现安全性也能减轻服务器的压力。
  g.dispose();
  try {
   ByteArrayOutputStream tmp = new ByteArrayOutputStream();
   ImageIO.write(image, "png", tmp);
   tmp.close();
   Integer contentLength = tmp.size();
   response.setHeader("content-length", contentLength + "");
   response.getOutputStream().write(tmp.toByteArray());// 将内存中的图片通过流动形式输出到客户端
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   try {
    response.getOutputStream().flush();
    response.getOutputStream().close();
   } catch (Exception e2) {
    e2.printStackTrace();
   }
  }
 }
 
}

4、总结

本文的内容到这就结束了,如果对里面的地方有不懂的地方,可以留言讨论。希望本文的内容对大家的学习工作能有所帮助。

标签:

相关文章

热门资讯

歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
沙雕群名称大全2019精选 今年最火的微信群名沙雕有创意
沙雕群名称大全2019精选 今年最火的微信群名沙雕有创意 2019-07-07
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分 2019-06-21
男生常说24816是什么意思?女生说13579是什么意思?
男生常说24816是什么意思?女生说13579是什么意思? 2019-09-17
返回顶部