- 原理
第一:首先在服务器端生成一个n个字符的字符串,然后保存到session,并将这个字符串转换成img图片,传递到浏览器端
第二:用户根据浏览器端显示的验证码图片,输入对应的字符,提交表单
第三:在服务端将用户提交的验证码字符【request域】和session服务端保存的验证码进行比较,
如果相等,就认为验证码输入正确,然后就可以验证用户名和密码是否正确,
如果用户名和密码正确:就允许登录,同时将用户信息保存到session中
如果用户名和密码不正确,直接重定向到登录页面。
如果不相等直接重定向到登录页面。 - 验证码代码
package com.ujiuye.common;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 验证码工具类
*/
public class ValidateCode {
private int width = 90;//验证码宽度 默认值:90
private int height = 40;//验证码高度 默认值:40
private int codeCount = 4;//验证码个数 默认值:4
private int lineCount = 19;//混淆线个数 默认值:19
private int fontSize = 20;//字体大小像素
//存储session中的key值 默认值:"validateCode"
private String sessionKey = "validateCode";
public ValidateCode() {
}
/**
* @param width 验证码宽度
* @param height 验证码高度
* @param fontSize 字体大小像素
*/
public ValidateCode(int width, int height, int fontSize) {
this.width = width;
this.height = height;
this.fontSize = fontSize;
}
/**
* @param width 验证码宽度
* @param height 验证码高度
* @param fontSize 字体大小像素
* @param sessionKey 存储session中的key值
*/
public ValidateCode(int width, int height, int fontSize, String sessionKey) {
this.width = width;
this.height = height;
this.fontSize = fontSize;
this.sessionKey = sessionKey;
}
/**
* @param width 验证码宽度
* @param height 验证码高度
* @param codeCount 验证码个数
* @param fontSize 字体大小像素
* @param sessionKey 存储session中的key值
*/
public ValidateCode(int width, int height, int codeCount, int fontSize, String sessionKey) {
this.width = width;
this.height = height;
this.codeCount = codeCount;
this.fontSize = fontSize;
this.sessionKey = sessionKey;
}
/**
* @param width 验证码宽度
* @param height 验证码高度
* @param codeCount 验证码个数
* @param lineCount 混淆线个数
* @param fontSize 字体大小像素
* @param sessionKey 存储session中的key值
*/
public ValidateCode(int width, int height, int codeCount, int lineCount, int fontSize, String sessionKey) {
this.width = width;
this.height = height;
this.codeCount = codeCount;
this.lineCount = lineCount;
this.fontSize = fontSize;
this.sessionKey = sessionKey;
}
char[] codeSequence = {'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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
/**
* 具体获取验证码的方法
*
* @param time time为时戳,这样的话可以避免浏览器缓存验证码
* @throws IOException
*/
public void getCode(HttpServletRequest request, HttpServletResponse response) {
//定义随机数类
Random r = new Random();
//定义存储验证码的类
StringBuilder builderCode = new StringBuilder();
//定义画布
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//得到画笔
Graphics g = buffImg.getGraphics();
//1.设置颜色,画边框
g.setColor(Color.gray);
g.drawRect(0, 0, width, height);
//2.设置颜色,填充内部
g.setColor(Color.white);
g.fillRect(1, 1, width - 2, height - 2);
//3.设置干扰线
// g.setColor(Color.gray);
for (int i = 0; i < lineCount; i++) {
int _R = (int) Math.floor(Math.random() * 256);
int _G = (int) Math.floor(Math.random() * 256);
int _B = (int) Math.floor(Math.random() * 256);
g.setColor(new Color(_R, _G, _B, 255));
g.drawLine(r.nextInt(width), r.nextInt(width), r.nextInt(width), r.nextInt(width));
}
//4.设置验证码
g.setColor(Color.blue);
//4.1设置验证码字体
g.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, fontSize));
for (int i = 0; i < codeCount; i++) {
char c = codeSequence[r.nextInt(codeSequence.length)];
builderCode.append(c);
g.drawString(c + "", ((width / codeCount) * i + 2), height * 4 / 5);
}
try {
//5.输出到屏幕
ServletOutputStream sos = response.getOutputStream();
ImageIO.write(buffImg, "png", sos);
//6.保存到session中
HttpSession session = request.getSession();
session.setAttribute("" + sessionKey + "", builderCode.toString());
//7.禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/png");
//8.关闭sos
sos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 调用过程
package com.ujiuye.sys.bean;
import com.ujiuye.common.ValidateCode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/code")
public class ValidateCodeController {
@RequestMapping(value = "getCode")
public void getCode(@RequestParam(value = "time") String time, HttpServletRequest request, HttpServletResponse response) {
ValidateCode code = new ValidateCode(100, 30, 4, 30, 25, "validateCode");
code.getCode(request, response);
}
}
前端:
<img id="image" src="${pageContext.request.contextPath}/code/getCode?time=false">
- 登录示例
/**
* 如果在重定向的时候想携带数据到页面
* 1、在目标方法参数上使用RedirectAttributes类型
* 2、在使用RedirectAttributes的时候需要在springmvc.xml中配置
* <mvc:view-controller path="/login" view-name="login"></mvc:view-controller>
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(Employee employee, String code, HttpSession session, RedirectAttributes attributes){
String validateCode = (String)session.getAttribute("validateCode");
//用户输入的验证码和session中的验证码做比较
if(code.equalsIgnoreCase(validateCode)){
//验证码验证成功完使验证码失效
session.removeAttribute("validateCode");
employee=employeeService.login(employee);
if (employee!=null){
session.setAttribute("loginUser",employee);
return "redirect:/index.jsp";
}else{
//重定向页面时将错误信息加载到页面
attributes.addFlashAttribute("errorMsg","用户名或者密码错误");
return "redirect:/login";
}
}
//重定向页面时将错误信息加载到页面
attributes.addFlashAttribute("errorMsg","验证码错误");
return "redirect:/login";
}
}
``