验证码工具类
package common;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
public class VerificationCode {
private int weight = 70; //验证码图片的长和宽
private int height = 30;
private String text; //用来保存验证码的文本内容
private Random r = new Random(); //获取随机数对象
private String[] fontNames = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"}; //字体数组
private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; //验证码数组
/**
* 获取随机的颜色
*/
private Color randomColor() {
//这里为什么是150,因为当r,g,b都为255时,即为白色,为了好辨认,需要颜色深一点。
int r = this.r.nextInt(150);
int g = this.r.nextInt(150);
int b = this.r.nextInt(150);
//返回一个随机颜色
return new Color(r, g, b);
}
/**
* 获取随机字体
*/
private Font randomFont() {
//获取随机的字体
int index = r.nextInt(fontNames.length);
String fontName = fontNames[index];
//随机获取字体的样式,0是无样式,1是加粗,2是斜体,3是加粗加斜体
int style = r.nextInt(4);
//随机获取字体的大小
int size = r.nextInt(5) + 24;
//返回一个随机的字体
return new Font(fontName, style, size);
}
/**
* 获取随机字符
*/
private char randomChar() {
int index = r.nextInt(codes.length());
return codes.charAt(index);
}
/**
* 画干扰线,验证码干扰线用来防止计算机解析图片
*/
private void drawLine(BufferedImage image) {
int num = 155;
//定义干扰线的数量
Graphics2D g = (Graphics2D) image.getGraphics();
for (int i = 0; i < num; i++) {
int x = r.nextInt(weight);
int y = r.nextInt(height);
int xl = r.nextInt(weight);
int yl = r.nextInt(height);
g.setColor(getRandColor(160, 200));
g.drawLine(x, y, x + xl, y + yl);
}
}
/**
* 创建图片的方法
*/
private BufferedImage createImage() {
//创建图片缓冲区
BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics2D g = (Graphics2D) image.getGraphics();
// 设定图像背景色(因为是做背景,所以偏淡)
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, weight, height);
//返回一个图片
return image;
}
/**
* 获取验证码图片的方法
*/
public BufferedImage getImage() {
BufferedImage image = createImage();
//获取画笔
Graphics2D g = (Graphics2D) image.getGraphics();
StringBuilder sb = new StringBuilder();
drawLine(image);
//画四个字符即可
for (int i = 0; i < 4; i++) {
//随机生成字符,因为只有画字符串的方法,没有画字符的方法,所以需要将字符变成字符串再画
String s = randomChar() + "";
//添加到StringBuilder里面
sb.append(s);
//定义字符的x坐标
float x = i * 1.0F * weight / 4;
//设置字体,随机
g.setFont(randomFont());
//设置颜色,随机
g.setColor(randomColor());
g.drawString(s, x, height - 5);
}
this.text = sb.toString();
return image;
}
/**
* 给定范围获得随机颜色
*/
Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
/**
* 获取验证码文本的方法
*/
public String getText() {
return text;
}
}
控制器
package controller;
import com.alibaba.fastjson.JSONObject;
import common.StringTools;
import common.VerificationCode;
import json.Msg;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
@Controller
@RequestMapping("/login")
public class SignCodeController {
/**
* 获取图片验证码
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@RequestMapping("/get")
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
VerificationCode verificationCode = new VerificationCode();
//获取验证码图片
BufferedImage image = verificationCode.getImage();
//获取验证码内容
String text = verificationCode.getText();
// randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer randomCode = new StringBuffer();
randomCode.append(text);
// 将验证码保存到Session中。
HttpSession session = request.getSession();
session.setAttribute("signcode", randomCode.toString());
System.out.println("session-signcode==>"+randomCode.toString());
// 禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
// 将图像输出到Servlet输出流中。
ServletOutputStream sos = response.getOutputStream();
ImageIO.write(image, "jpeg", sos);
sos.flush();
sos.close();
}
/**
* 验证图片验证码
* @param request
* @param signcode
* @return
*/
@RequestMapping("/check")
@ResponseBody
public JSONObject check(HttpServletRequest request, String signcode) {
HttpSession session = request.getSession();
String signcodeSession = (String) session.getAttribute("signcode");
System.out.println("signcode==>"+signcode);
System.out.println("signcodeSession==>"+signcodeSession);
if (StringTools.isNull(signcode)) {
return Msg.Error();
}
if (StringTools.isNull(signcodeSession)) {
return Msg.Error();
}
//验证的时候不区分大小写
if (signcode.equalsIgnoreCase(signcodeSession)) {
return Msg.OK();
}
return Msg.Error();
}
}
<html lang="en">
<head>
<meta charset="UTF-8" >
<title>验证码title>
<h2>验证码h2>
<img border=0 src="http://localhost:8080/login/get" id="imageMask" onclick="myReload()" style="cursor: pointer">
<br/>
<input type="text" id="signcode"/>
<button value="提交" onclick="check()" style="height: 20px;width: 60px"/>提交
head>
<body>
<script type="text/javascript" src="js/jquery-1.11.0.min.js">script>
<script type="text/javascript" src="js/mui.min.js">script>
<script type="text/javascript">
//用于刷新验证码
function myReload() {
document.getElementById("imageMask").src = document.getElementById("imageMask").src + "?nocache=" + new Date().getTime();
}
function check() {
var vcode = $('#signcode').val();
console.log("vcode==>"+vcode)
$.ajax({
url: "http://localhost:8080/login/check",
type: 'GET',
data: {
signcode: vcode,
},
dataType:"json",
xhrFields: {
withCredentials: true
},
success: function (result) {
console.log(result)
if(result.code==200){
window.location.href="success.html";
}
}
})
}
script>
body>
html>
1.配置拦截器spring-web.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
bean>
<context:component-scan base-package="controller"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="interceptor.Interceptor">bean>
mvc:interceptor>
mvc:interceptors>
beans>
2.拦截器Interceptor
package interceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Interceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String url = request.getHeader("Origin");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.setHeader("Access-Control-Allow-Origin", url);
response.addHeader("Access-Control-Allow-Credentials", "true");
return true;
}
}
注意:
1.前端ajax访问时要加上“xhrFields: {withCredentials: true}” ,实现session可以传递;
2.配置拦截器,response.setHeader(“Access-Control-Allow-Origin”, “*”),实现跨域访问问题;
3.配置拦截器,response.addHeader(“Access-Control-Allow-Credentials”, “true”),实现session传值问题;*
4.配置拦截器,如果配置了Access-Control-Allow-Credentials=true,则跨域拦截Access-Control-Allow-Origin 必须是指定的url,response.setHeader(“Access-Control-Allow-Origin”, url);