javaweb项目登录页面添加验证码
- 改造登录页面 index.jsp 添加验证码输入框,并且添加刷新验证码的前端JavaScript函数index.jsp代码如下 <% @ page language = “java” contentType = “text/html; charset=utf-8”
pageEncoding = “utf-8” %>
<% @taglib uri = “#34; prefix = “c” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “#34;>
<html>
<head>
<meta http-equiv = “Content-Type” content = “text/html; charset=utf-8” >
<title> Insert title here </title>
</head>
<body>
<font color = “red” size = “5px” > ${msg} </font>
<form action = ” <% = request . getContextPath ()%> /login” method = “post” >
用户名: <input type = “text” name = “userName” /><br/>
密码: <input type = “password” name = “password” /><br/>
验证码: <input type = “text” name = “verifyCode” /> <img src = ” <% = request . getContextPath ()%> /verifyCode” onClick = “change()” id = “picture” /> 看不清? <input type = “button” value = “换一张” onClick = “change()” /><br/>
<input type = “submit” value = “登录” />
</form>
</body>
<script language = “javascript” type = “text/javascript” >
pic . src = ” <% = request . getContextPath ()%> / verifyCode ? time = ” + random;}
</script>
</html> 我们在换一张按钮和img标签上都加上onClick事件,提高用户体验var random = new Date().getTime() 这个是生成一个随机数,防止浏览器缓存导致不请求后端验证码接口 - 编写验证码生成接口,这里我们为了方便,直接使用@Web servlet 注解来指定 请求路径,你也可以在web.xml中配置此servlet 具体请看一下之前的博文验证码servlet如下 package com . cgy . demos . web . servlet ;
import javax . servlet . ServletException ;
import javax . servlet . annotation . WebServlet ;
import javax . servlet . http . HttpServlet ;
import javax . servlet . http . HttpServletRequest ;
import javax . servlet . http . HttpServletResponse ;
import java . awt . * ;
import java . awt . image . BufferedImage ;
import java . io . IOException ;
import java . util . Random ;
public class VerifyCodeServlet extends HttpServlet {
@ Override
protected void doGet ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
this . doPost ( req , resp );
}
protected void doPost ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
//声明验证码
int width = 60 ;
int height = 30 ;
String data = “ABCDEFGHJKLMNPQRSTUVWXYZ23456789abcdefghijklmnpqrstuvwxyz” ; //随机字符字典,其中0,o,1,I 等难辨别的字符最好不要
Random random = new Random (); //随机类
//1 创建图片数据缓存区域(核心类)
BufferedImage image = new BufferedImage ( width , height , BufferedImage . TYPE_INT_RGB ); //创建一个彩色的图片
//2 获得画板(图片,ps图层),绘画对象。
Graphics g = image . getGraphics ();
//3 选择颜色,画矩形3,4步是画一个有内外边框的效果
g . setColor ( Color . BLACK );
g . fillRect ( 0 , 0 , width , height );
//4白色矩形
g . setColor ( Color . WHITE );
g . fillRect ( 1 , 1 , width – 2 , height – 2 );
StringBuilder builder = new StringBuilder ();
//设置字体颜色
g . setFont ( new Font ( “宋体” , Font . BOLD & Font . ITALIC , 20 ));
for ( int i = 0 ; i < 4 ; i ++ ){
//随机颜色
g . setColor ( new Color ( random . nextInt ( 255 ), random . nextInt ( 255 ), random . nextInt ( 255 )));
int index = random . nextInt ( data . length ());
String str = data . substring ( index , index + 1 );
builder . append ( str );
g . drawString ( str , ( width / 6 ) * ( i + 1 ) , 20 );
}
//给图中绘制噪音点,让图片不那么好辨别
for ( int j = 0 , n = random . nextInt ( 100 ); j < n ; j ++ ){
g . setColor ( Color . RED );
g . fillRect ( random . nextInt ( width ), random . nextInt ( height ), 1 , 1 ); //随机噪音点
}
String tempStr = builder . toString ();
req . get session (). setAttribute ( “verifyCode” , tempStr );
ImageIO . write ( image , ” jpg ” , resp . getOutputStream ());
}
}
验证码生成的代码可以不做重点,当做工具类即可,生成的验证码存入session中
- 登录表单提交后的LoginServlet改造,添加验证码的校验逻辑添加验证码校验后的LoginServlet代码如下 package com . cgy . demos . web . servlet ;
import javax . servlet . http . HttpServlet ;
import javax . servlet . http . HttpServletRequest ;
import javax . servlet . http . HttpServletResponse ;
import java . io . IOException ;
@Override
protected void doGet ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
this . doPost ( req , resp );
}
protected void doPost ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
String userName = req . getParameter ( “userName” );
String password = req . getParameter ( “password” );
String verifyCode = req . getParameter ( “verifyCode” );
//为防止机器请求 第一步要先验证验证码是否正确
String cacheCode = ( String ) req . getSession (). getAttribute ( “verifyCode” );
if ( StringUtils . isBlank ( verifyCode )) {
req . setAttribute ( “msg” , “验证码不能为空” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( ! verifyCode . equalsIgnoreCase ( cacheCode )) { //这里验证码不区分大小写
req . setAttribute ( “msg” , “验证码错误” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
req . setAttribute ( “msg” , “密码不能为空” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( StringUtils . isBlank ( userName )) {
req . setAttribute ( “msg” , “用户名不能为空” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( ! userName . equals ( “admin” )) {
req . setAttribute ( “msg” , “用户名不正确” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( ! password . equals ( “123456” )) {
req . setAttribute ( “msg” , “密码不正确” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
req . getSession (). setAttribute ( “userName” , userName );
req . getSession (). removeAttribute ( “verifyCode” );
package com . cgy . demos . web . servlet ;
import javax . servlet . http . HttpServlet ;
import javax . servlet . http . HttpServletRequest ;
import javax . servlet . http . HttpServletResponse ;
import java . io . IOException ;
@Override
protected void doGet ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
this . doPost ( req , resp );
}
protected void doPost ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
String userName = req . getParameter ( “userName” );
String password = req . getParameter ( “password” );
String verifyCode = req . getParameter ( “verifyCode” );
//为防止机器请求 第一步要先验证验证码是否正确
String cacheCode = ( String ) req . getSession (). getAttribute ( “verifyCode” );
if ( StringUtils . isBlank ( verifyCode )) {
req . setAttribute ( “msg” , “验证码不能为空” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( ! verifyCode . equalsIgnoreCase ( cacheCode )) { //这里验证码不区分大小写
req . setAttribute ( “msg” , “验证码错误” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
req . setAttribute ( “msg” , “密码不能为空” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( StringUtils . isBlank ( userName )) {
req . setAttribute ( “msg” , “用户名不能为空” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( ! userName . equals ( “admin” )) {
req . setAttribute ( “msg” , “用户名不正确” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
if ( ! password . equals ( “123456” )) {
req . setAttribute ( “msg” , “密码不正确” );
req . getRequestDispatcher ( “/WEB-INF/index.jsp” ). forward ( req , resp );
return ;
}
req . getSession (). setAttribute ( “userName” , userName );
req . getSession (). removeAttribute ( “verifyCode” );
req . getRequestDispatcher ( “/WEB-INF/home.jsp” ). forward ( req , resp );}
}}
}
验证码,用户名和密码校验通过后,在session中添加用户名
校验完成后 最好能够把 session中的验证码 删除 ,这种数据就是一次性数据,验证完了就没啥用处了。如果不清除,这个时候刚好网站的请他功能也要输入验证码的话,就会受到影响
- 启动项目,测试验证码功能
点击换一张 点击验证码图片 能够刷新验证码 ,达到了预期效果
输入错误的验证码能够刷新页面并提示错误信息
输入正确用户名和密码验证码 也能够正常的登录