验证码最终效果:除了最后一个输入框样式没写好以及没有居中对齐外,自己觉得还可以
验证码实现步骤:
1.在工具包(util)中写一个验证码的方法(ImageUtil)
2.创建ImageServlet,生成验证码和图片,验证码放session中,并且输出图片
3.在登录页显示图片:将图片地址指向ImageServlet
4.输入验证码,点击提交
5.在LoginServlet中,将提交的验证码和session中的验证码进行比对
步骤详解:
1.在工具包(util)中写一个验证码的方法(ImageUtil):
package com.cyzy.util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
// 生成 验证码 和 验证码图片 的类
public final class ImageUtil {
private static final char[] chars = { '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J',
'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z' };
private static final int SIZE = 4; // 验证码图片中文字的个数
private static final int LINES = 3; // 验证码图片中的干扰线的数量
private static final int WIDTH = 80; // 验证码图片的宽度
private static final int HEIGHT = 34; // 验证码图片的高度
private static final int FONT_SIZE = 19;// 验证码图片中文字的大小
/**
* 生成验证码和验证码图片的方法,并封装在Map中。
*
* 其中Map的key是验证码,Map的value是验证码图片。
*/
public static Map<String, BufferedImage> createImage() {
StringBuffer sb = new StringBuffer();
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics graphic = image.getGraphics();
graphic.setColor(Color.LIGHT_GRAY);
graphic.fillRect(0, 0, WIDTH, HEIGHT);
Random ran = new Random();
// 画随机字符
for (int i = 1; i <= SIZE; i++) {
int r = ran.nextInt(chars.length);
graphic.setColor(getRandomColor());
graphic.setFont(new Font(null, Font.BOLD + Font.ITALIC, FONT_SIZE));
graphic.drawString(chars[r] + "", (i - 1) * WIDTH / SIZE,
HEIGHT / 2);
sb.append(chars[r]);// 将字符保存,存入Session
}
// 画干扰线
for (int i = 1; i <= LINES; i++) {
graphic.setColor(getRandomColor());
graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), ran
.nextInt(WIDTH), ran.nextInt(HEIGHT));
}
Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
map.put(sb.toString(), image);
return map;
}
/**
* 将图片传入输入流的方法
*/
public static InputStream getInputStream(BufferedImage image)
throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
encoder.encode(image);
byte[] imageBts = bos.toByteArray();
InputStream in = new ByteArrayInputStream(imageBts);
return in;
}
// 产生随机颜色的方法
private static Color getRandomColor() {
Random ran = new Random(); // 随机函数
// 产生随机的RGB颜色
Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran
.nextInt(256));
return color;
}
}
2.创建ImageServlet,生成验证码和图片,验证码放session中,并且输出图片
(1)、创建Servlet:右键-->new-->Servlet-->ImageServlet
(2)、
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, BufferedImage> imageMap=ImageUtil.createImage();
//得到验证码
String code=imageMap.keySet().iterator().next();//用于Session进行校验
request.getSession().setAttribute("code", code);
//获取图片
BufferedImage image=imageMap.get(code);
//输出图片
ServletOutputStream out=response.getOutputStream();
ImageIO.write(image, "jpg", out);
}
3.在登录页显示图片:将图片地址指向ImageServlet(出现了无法访问 [ 生成验证码的Servlet ],是因为什么原因呢,我百思不得其解)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>校务管理系统</title>
<style type="text/css">
a {
margin-left: 420px;
}
</style>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/css/index.css">
</head>
<body>
<div class="wrapper">
<div class="content">
<h1>校务管理系统</h1>
<form action="${pageContext.request.contextPath}/LoginServlet"
method="post">
<input type="hidden" name="loginAction" value="login">
<ul>
<li>用户名:</li>
<li><input type="text" placeholder="请输入用户名" name="userName"
id="userName"></li>
<li>密码:</li>
<li><input type="password" placeholder="请输入密码" name="password"
id="password"></li>
<li>验证码:</li>
<li> <input type="text" name="code" id="code"
placeholder="请输入验证码" />
<img src="${pageContext.request.contextPath}/ImageServlet"
id="imageCode" onclick="getCode()" />
</li>
<li><input type="submit" value="登陆"><input
type="reset" value="重置"></li>
</ul>
<a href="${pageContext.request.contextPath}/register.jsp">前往注册页面</a>
</form>
</div>
</div>
</body>
<script type="text/javascript">
function getCode() {
var image = document.getElementById("imageCode");
image.src = "${pageContext.request.contextPath}/ImageServlet?"
+ Math.random();
}
</script>
</html>
出现无法生成验证码图片的问题后-->我debug发现,自己的ImageServlet[生成验证码的Servlet]根本没有运行-->然后把
SessionFilter过滤器一开始没有判断这个ImageServlet-->下图的意思是说除了这些可以直接访问之外,其他的Servlet都要先登录才能访问,否则会提示会话失效。
4.输入验证码,点击提交 【用户操作】
5.在LoginServlet中,将提交的验证码和session中的验证码进行比对
(1)、在ImageServlet中存有session中的验证码
(2)、LoginServlet中
private void login(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
String code=request.getParameter("code");
String sessionCode=(String)request.getSession().getAttribute("code");
if(!code.equals(sessionCode)) {
PrintWriter out =response.getWriter();
out.println("<script>");
out.println("window.alert('请输入正确的验证码');");
out.println("window.location.href='"+request.getContextPath()+"/index.jsp';");
out.println("</script>");
return;
}
//查询用户是不是存在
String userName=request.getParameter("userName");
String password=request.getParameter("password");
UserService userService=(UserService)ServiceFactory.getServiceImpl(UserService.class.getName());
User user=userService.login(userName, password);
if(user!=null) {
HttpSession session=request.getSession();
//session.setMaxInactiveInterval(10);//超时时间以秒为单位
session.setAttribute("loginUser", user);
//还要查询此用户所拥有的菜单
//菜单列表扔到request/session范围
List<Menu> menuList=new ArrayList<Menu>();
MenuService menuService=(MenuService)ServiceFactory.getServiceImpl(MenuService.class.getName());
menuList=menuService.queryMenuByuserName(userName);
request.getSession().setAttribute("menuList", menuList);
//因为页面是由iframe组成,其他页面request没有办法取到
//request.setAttribute("menuList", menuList);
request.getRequestDispatcher("/admin/adminMain.jsp").forward(request, response);
}else {
PrintWriter out =response.getWriter();
out.println("<script>");
out.println("window.alert('用户不存在');");
out.println("window.location.href='http://localhost:8080/JF190902/index.jsp';");
out.println("</script>");
}
}