参考:
SpringMVC (SSM) 配置Kaptcha验证码_CodingAnHour-优快云博客
前提:
导入jar包:
原生servlet配置
前端部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员注册页面</title>
<%-- 静态包含 base标签、css样式、jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
<script type="text/javascript">
// 页面加载完成之后
$(function () {
$("#username").blur(function () {
//1. 获取用户名,通过jQuery中的ajax实现
var username = this.value;
$.getJSON("http://localhost:8080/book/userServlet", "action=ajaxExitsUsername&username="+username, function (data) {
if(data.exitsUsername){
$("span.errorMsg").text("用户名已存在!");
}else{
$("span.errorMsg").text("用户名可用!");
}
});
});
// 给验证码的图片,绑定单击事件
$("#code_img").click(function () {
// 在事件响应的function函数中有一个this对象。这个this对象,是当前正在响应事件的dom对象
// src属性表示验证码img标签的 图片路径。它可读,可写
// alert(this.src);
this.src = "${basePath}kaptcha.jpg?d=" + new Date();
});
// 给注册绑定单击事件
$("#sub_btn").click(function () {
// 验证用户名:必须由字母,数字下划线组成,并且长度为5到12位
//1 获取用户名输入框里的内容
var usernameText = $("#username").val();
//2 创建正则表达式对象
var usernamePatt = /^\w{5,12}$/;
//3 使用test方法验证
if (!usernamePatt.test(usernameText)) {
//4 提示用户结果
$("span.errorMsg").text("用户名不合法!");
return false;
}
// 验证密码:必须由字母,数字下划线组成,并且长度为5到12位
//1 获取用户名输入框里的内容
var passwordText = $("#password").val();
//2 创建正则表达式对象
var passwordPatt = /^\w{5,12}$/;
//3 使用test方法验证
if (!passwordPatt.test(passwordText)) {
//4 提示用户结果
$("span.errorMsg").text("密码不合法!");
return false;
}
// 验证确认密码:和密码相同
//1 获取确认密码内容
var repwdText = $("#repwd").val();
//2 和密码相比较
if (repwdText != passwordText) {
//3 提示用户
$("span.errorMsg").text("确认密码和密码不一致!");
return false;
}
// 邮箱验证:xxxxx@xxx.com
//1 获取邮箱里的内容
var emailText = $("#email").val();
//2 创建正则表达式对象
var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
//3 使用test方法验证是否合法
if (!emailPatt.test(emailText)) {
//4 提示用户
$("span.errorMsg").text("邮箱格式不合法!");
return false;
}
// 验证码:现在只需要验证用户已输入。因为还没讲到服务器。验证码生成。
var codeText = $("#code").val();
//去掉验证码前后空格
// alert("去空格前:["+codeText+"]")
codeText = $.trim(codeText);
// alert("去空格后:["+codeText+"]")
if (codeText == null || codeText == "") {
//4 提示用户
$("span.errorMsg").text("验证码不能为空!");
return false;
}
// 去掉错误信息
$("span.errorMsg").text("");
});
});
</script>
<style type="text/css">
.login_form{
height:420px;
margin-top: 25px;
}
</style>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎注册</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>注册尚硅谷会员</h1>
<span class="errorMsg">
${ requestScope.msg }
</span>
</div>
<div class="form">
<form action="userServlet" method="post">
<input type="hidden" name="action" value="regist">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名"
value="${requestScope.username}"
autocomplete="off" tabindex="1" name="username" id="username" />
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码"
autocomplete="off" tabindex="1" name="password" id="password" />
<br />
<br />
<label>确认密码:</label>
<input class="itxt" type="password" placeholder="确认密码"
autocomplete="off" tabindex="1" name="repwd" id="repwd" />
<br />
<br />
<label>电子邮件:</label>
<input class="itxt" type="text" placeholder="请输入邮箱地址"
value="${requestScope.email}"
autocomplete="off" tabindex="1" name="email" id="email" />
<br />
<br />
<label>验证码:</label>
<input class="itxt" type="text" name="code" style="width: 80px;" id="code" />
<img id="code_img" alt="" src="kaptcha.jpg" style="float: right; margin-right: 40px; width: 110px; height: 30px;">
<br />
<br />
<input type="submit" value="注册" id="sub_btn" />
</form>
</div>
</div>
</div>
</div>
</div>
<%--静态包含页脚内容--%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
将KaptchaServlet配置到web.xml中:
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
已经将UserServlet.java配置到web.xml中
则UserServlet.java中的regist方法处理请求:
/**
* 处理注册功能
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取Session中的验证码,获取本次的验证码,为了和用户输入的验证码进行对比是否正确
String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
//删除Session中的验证码,保证每次刷新后的验证码都是不同的
request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
//获取客户端请求的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
String code = request.getParameter("code");//获取用户输入的验证码
System.out.println(request.getParameterMap());
User user = WebUtils.copyParamToBean(request.getParameterMap(), new User());
//检查1 验证码是否正确
if(token!= null && token.equalsIgnoreCase(code)){
//检查2 用户名是否可用
if(userService.exitsUsername(username)){
System.out.println("用户名[" + username +"]已存在!");
//把回显到jsp页面的内容保存到request域中
request.setAttribute("msg", "用户名已存在!");
request.setAttribute("username", "username");
request.setAttribute("email", email);
request.getRequestDispatcher("/pages/user/regist.jsp").forward(request, response);
}else{
//userService.registUser(new User(null, username, password, email));
userService.registUser(user);
request.getRequestDispatcher("/pages/user/regist_success.jsp").forward(request, response);
}
}else{
//把回显到jsp页面的内容保存到request域中
request.setAttribute("msg", "验证码错误!");
request.setAttribute("username", username);
request.setAttribute("email", email);
System.out.println("验证码[" + code + "]错误");
request.getRequestDispatcher("/pages/user/regist.jsp").forward(request, response);
}
}
springMVC配置
开始之前:
先去看下KaptchaServlet原生实现:
再回头看该类的属性:
初始化方法中:
config类中:
config类部分展示:
正式开始springMVC对Kaptcha验证码的配置
部分前端:
<%@ 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>
<%-- 静态包含 base标签、css样式、jQuery文件 --%>
<%@ include file="../common/head.jsp"%>
<style type="text/css">
.login_form{
height:500px;
margin-top: 30px;
}
.login_banner{
height:580px;
background-color: #39987c;
}
</style>
<script type="text/javascript">
$(function () {
//回显用户名是否可用
$("#username").blur(function () {
// 在事件响应的function函数中有一个this对象。这个this对象,是当前正在响应事件的dom对象
var username = this.value;
$.getJSON("http://localhost:8080/bookstore/regist/ajaxExitsUsername", "&username="+username, function(data){
if(data.exitsUsername){
$("span.errorMsg").text("用户名已存在!");
}else{
$("span.errorMsg").text("用户名可用!");
}
});
});
//给验证码的图片,绑定单击事件
$("#code_img").click(function () {
// 在事件响应的function函数中有一个this对象。这个this对象,是当前正在响应事件的dom对象
// src属性表示验证码img标签的 图片路径。它可读,可写
// 每次点击的时间戳不同,所以验证码的图像不同
//alert(this.src);//http://localhost:8080/bookstore/kaptcha.jpg
this.src = "${basePath}kaptcha.jpg?timeStamp=" + new Date();
});
});
</script>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎注册</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>注册尚硅谷会员</h1>
<span class="errorMsg">${ requestScope.msg }</span>
</div>
<div class="form">
<form action="regist" method="post">
<input type="hidden" name="action" value="regist">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名"
value="${requestScope.username}"
autocomplete="off" tabindex="1" name="username" id="username" />
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码"
autocomplete="off" tabindex="1" name="password" id="password" />
<br />
<br />
<label>确认密码:</label>
<input class="itxt" type="password" placeholder="确认密码"
autocomplete="off" tabindex="1" name="repwd" id="repwd" />
<br />
<br />
<label>手机号码:</label>
<input class="itxt" type="text" placeholder="请输入手机号码"
value="${requestScope.phone}"
autocomplete="off" tabindex="1" name="email" id="phone" />
<br />
<br />
<label>电子邮件:</label>
<input class="itxt" type="text" placeholder="请输入邮箱地址"
value="${requestScope.email}"
autocomplete="off" tabindex="1" name="email" id="email" />
<br />
<br />
<label>验证码:</label>
<input class="itxt" type="text" name="code" style="width: 85px; height: 28px" id="code" />
<img id="code_img" alt="" src="kaptcha.jpg" style="float: right; margin-right: 40px;">
<br />
<br />
<input type="submit" value="注册" id="sub_btn" />
</form>
</div>
</div>
</div>
</div>
</div>
<%--静态包含页脚内容--%>
<%@include file="../common/footer.jsp"%>
</body>
</html>
这次没有在web.xml中配置KaptchaServlet程序,因为我们想要通过controller层实现
配置到spring中:
<!-- 配置Kaptcha验证码 -->
<bean id="kaptcha" class="com.google.code.kaptcha.impl.DefaultKaptcha">
<property name="config">
<bean class="com.google.code.kaptcha.util.Config">
<constructor-arg>
<props>
<!-- 验证码宽度 -->
<prop key="kaptcha.image.width">120</prop>
<!-- 验证码高度 -->
<prop key="kaptcha.image.height">50</prop>
<!-- 生成验证码内容范围 -->
<!-- <prop key="kaptcha.textproducer.char.string">123456789abcDeFGHjkLmnoQqrsTUVWXYZ</prop> -->
<!-- 验证码个数 -->
<!-- <prop key="kaptcha.textproducer.char.length">4</prop> -->
<!-- 是否有边框 -->
<!-- <prop key="kaptcha.border">no</prop> -->
<!-- 边框颜色 -->
<!-- <prop key="kaptcha.border.color">105,179,90</prop> -->
<!-- 边框厚度 -->
<!-- <prop key="kaptcha.border.thickness">1</prop> -->
<!-- 验证码字体颜色 -->
<!-- <prop key="kaptcha.textproducer.font.color">black</prop> -->
<!-- 验证码字体大小 -->
<!-- <prop key="kaptcha.textproducer.font.size">30</prop> -->
<!-- 验证码所属字体样式 -->
<!-- <prop key="kaptcha.textproducer.font.names">楷体</prop> -->
<!-- 干扰线颜色 -->
<!-- <prop key="kaptcha.noise.color">black</prop> -->
<!-- 验证码文本字符间距 -->
<!-- <prop key="kaptcha.textproducer.char.space">3</prop> -->
<!-- 图片样式 :阴影-->
<!-- <prop key="kaptcha.obscurificator.impl">com.google.code.kaptcha.impl.ShadowGimpy</prop> -->
</props>
</constructor-arg>
</bean>
</property>
</bean>
controller层:
@Controller
public class KaptachaController {
@Autowired
private Producer kaptchaProducer;
@RequestMapping(value = "/kaptcha.jpg", method = RequestMethod.GET)
public ModelAndView getCaptchaImage(@RequestParam(value = "timeStamp", required = false) String timeStamp,
HttpServletRequest request, HttpServletResponse response) throws IOException {
ModelAndView mav = new ModelAndView();
//以下来自于com.google.code.kaptcha.servlet.KaptchaServlet
response.setDateHeader("Expires", 0L);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
String capText = this.kaptchaProducer.createText();
request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
if(timeStamp != null) {
System.out.println("触发点击事件");
request.getSession().setAttribute(Constants.KAPTCHA_SESSION_DATE, timeStamp); //将原有的常量对应的值变成现在的时间戳值
}
BufferedImage bi = this.kaptchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
return null;
}
}
业务功能controller层的实现:
@RequestMapping(value="regist")
public String regist(String username, String password, String phone, String email, String code,
HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
//获取session中的验证码,本次的验证码
String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
//删除Session中本次的验证码,保证每次刷新验证码都不一样
request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
User user = new User(username, password, phone, email);
System.out.println(username);
//检查1 验证码是否正确
if(token!= null && token.equalsIgnoreCase(code)){
//检查2 用户名是否可用
if(username == "" || username == null) {
System.out.println("用户名[" + username +"]不可用");
return "forward:regist/userRegist";
}else if(userService.exitsUsername(username)){
System.out.println("用户名[" + username +"]已存在!");
//把回显到jsp页面的内容保存到request域中
map.put("msg", "用户名已存在!");
map.put("username", username);
map.put("phone", phone);
map.put("email", email);
return "forward:regist/userRegist";
}else{
userService.registUser(user);
return "forward:regist/registSuccess";
}
}else{
//把回显到jsp页面的内容保存到request域中
map.put("msg", "验证码错误!");
map.put("username", username);
map.put("phone", phone);
map.put("email", email);
System.out.println("验证码[" + code + "]错误");
return "forward:regist/userRegist";
}
}
@RequestMapping(value="regist/ajaxExitsUsername")
@ResponseBody
public String ajaxExitsUsername(String username) {
//调用UserService.exitsUsername();
boolean exitsUsername = userService.exitsUsername(username);
//把返回的结果封装成map对象
HashMap<String, Object> resultMap = new HashMap<>();
resultMap.put("exitsUsername", exitsUsername);
Gson gson = new Gson();
String json = gson.toJson(resultMap);
return json;
}