Servlet---登录界面添加验证码
基本思路
在网页设置的登录login.jsp文件里加上输入验证码的操作,引入带有验证码的图片。生成验证码的CodeServlet太过麻烦不需要自己写,去网上找一个即可**,但是,要在获得的生成验证码图片文件中将验证码图片中的随机数放进session以获取用于验证。**并且设置一个验证码点击刷新事件(会用到jQuery)。
具体步骤
1.codeServlet
@WebServlet("/code")
public class CodeServlet extends HttpServlet {
private static final long serialVersionUID = 2376992603034716655L;
private final Font mFont = new Font("Arial Black", Font.PLAIN, 15); // 设置字体
private final int lineWidth = 2; // 干扰线的长度=1.414*lineWidth
private final int width = 88; // 定义图形大小
private final int height = 25; // 定义图形大小
private final int count = 200;
private Color getRandColor(int fc, int bc) { // 取得给定范围随机颜色
final Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
final int r = fc + random.nextInt(bc - fc);
final int g = fc + random.nextInt(bc - fc);
final int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
// 处理post
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
response.reset();
// 设置页面不缓存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/gif");
// 在内存中创建图象
final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
final Graphics2D g = (Graphics2D) image.getGraphics();
// 生成随机类
final Random random = new Random();
// 设定背景色
g.setColor(getRandColor(200, 250)); // ---1
g.fillRect(0, 0, width, height);
// 设定字体
g.setFont(mFont);
// 画边框
g.setColor(getRandColor(0, 20)); // ---2
// 距离
g.drawRect(0, 0, width - 1, height - 1);
// 随机产生干扰线,使图象中的认证码不易被其它程序探测到
for (int i = 0; i < count; i++) {
g.setColor(getRandColor(150, 200)); // ---3
final int x = random.nextInt(width - lineWidth - 1) + 1; // 保证画在边框之内
final int y = random.nextInt(height - lineWidth - 1) + 1;
final int xl = random.nextInt(lineWidth);
final int yl = random.nextInt(lineWidth);
g.drawLine(x, y, x + xl, y + yl);
}
// 取随机产生的认证码(4位数字)
String sRand = "";
for (int i = 0; i < 4; i++) {
final String rand = String.valueOf(random.nextInt(10));
sRand += rand;
// 将认证码显示到图象中,调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.setColor(new Color(20 + random.nextInt(130), 20 + random.nextInt(130), 20 + random.nextInt(130))); // --4--50-100
// 第一个参数是要画上去的字符串 后面两个参数是针对 (0,0) x轴和y轴
g.drawString(rand, (13 * i) + 10, 20);
}
// 把生成的随机数,保存到session里面
HttpSession session = request.getSession();
session.setAttribute("sessionCode", sRand);
// 图象生效
// 它的作用是销毁程序中指定的图形界面资源,如果在使用了graphics获得windows一些图形资源,而不进行关闭的话,由于后期多人使用就会造成内存溢出的情况的,导致程序卡死。
g.dispose();
OutputStream os = response.getOutputStream();
// 输出图象到页面
ImageIO.write(image, "PNG", os);
os.flush();
os.close();
}
}
2.网页设置
注意这一句,在获得的路径后加了一串随机数,因为每次点击图片切换都是在发送相同的请求,为了避免服务器不接受相同的许多请求,加上随机数会让请求变的各不相同。
$("#imageCode").attr('str',"<%=request.getContextPath()%>/code?" + Math.random() );
只截取body部分
<body>
<form action="<%=request.getContextPath()%>/user?method=login" method="post">
用户名:<input type="text" name="name"/><br/>
密码:<input type="password" name="password"/><br/>
验证码:<input type="text" name="code"/><img src="<%=request.getContextPath()%>/code" id="imgCode" onclick="refreshCode()"/><br />
<input type="submit" value="登录"/>
</form>
<script src="<%=request.getContextPath()%>/static/jquery-2.1.4.js" type="text/javascript" charset="UTF-8"></script>
<script type="text/javascript">
function refreshCode(){
$("#imageCode").attr('str',"<%=request.getContextPath()%>/code?" + Math.random() );
}
</script>
</body>
2.放行
加入图片后我们会发现由于被拦截我们的界面又被重定向回了登录界面,所以修改之前过滤器loginFilter中doFilter以达到放行效果。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("loginFilter.doFilter");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String servletPath = httpServletRequest.getServletPath();
System.out.println("servletPath = " + servletPath);
String method = httpServletRequest.getParameter("method");
System.out.println("method = " + method);
if (servletPath.equals("/login.jsp")
|| (servletPath.equals("/user") && method.equals("login"))
|| servletPath.equals("/fail.jsp")
|| servletPath.equals("/code")
|| servletPath.endsWith(".js")
|| servletPath.endsWith(".css")){
chain.doFilter(request,response);
return;
}
HttpSession httpSession = httpServletRequest.getSession();
User user = (User) httpSession.getAttribute("user");
System.out.println("user = " + user);
if (user == null){
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/login.jsp");
return;
}
chain.doFilter(request,response);
}
3.设置优先检查验证码
点击提交submit可以将在网页输入的用户名、密码和验证码一并传输给userServlet的login方法,我们要去配置先验证验证码,只要验证码错误,之后的代码就不再运行。
String code = req.getParameter("code");
HttpSession httpSession = req.getSession();
String sessionCode = (String) httpSession.getAttribute("sessionCode");
if(!sessionCode.equals(code)){
resp.sendRedirect(req.getContextPath() + "/login.jsp");
return;
}