一、利用Cookie实现Session跟踪
1、 如果WEB服务器处理某个访问请求时创建了新的HttpSession对象,它将把会话标识号作为一个Cookie项加入到响应消息中,通常情况下,浏览器在随后发出的访问请求中又将会话标识号以Cookie的形式回传给WEB服务器。
2、 WEB服务器端程序依据回传的会话标识号就知道以前已经为该客户端创建了HttpSession对象,不必再为该客户端创建新的HttpSession对象,而是直接使用与该会话标识号匹配的HttpSession对象,通过这种方式就实现了对同一个客户端的会话状态的跟踪。
二、利用URL重写实现Session跟踪
1、Servlet规范中引入了一种补充的会话管理机制,它允许不支持Cookie的浏览器也可以与WEB服务器保持连续的会话。这种补充机制要求在响应消息的实体内容中必须包含下一次请求的超链接,并将会话标识号作为超链接的URL地址的一个特殊参数。
2、 将会话标识号以参数形式附加在超链接的URL地址后面的技术称为URL重写。如果在浏览器不支持Cookie或者关闭了Cookie功能的情况下,WEB服务器还要能够与浏览器实现有状态的会话,就必须对所有可能被客户端访问的请求路径(包括超链接、form表单的action属性设置和重定向的URL)进行URL重写。
3、 HttpServletResponse接口中定义了两个用于完成URL重写方法:
a) encodeURL方法
b) encodeRedirectURL方法
Cookie功能没有被关闭
url重写
第一次提交请求,在请求消息没有包含sessionid的cookie。产生应答的时候用URL重写的技术
当cookie没有被禁掉时,以后再提交请求的时候,请求消息中就会包含sessionid的cookie
out.print(“<a href=’session4?JSESSION=’>xxx</a>”);
三、利用Session实现一次性验证码
1、 原理
1) 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码,其原理与利用Session防止表单重复提交的原理基本一样,只是将表单标识号变成了验证码的形式,并且要求用户将提示的验证码手工填写进一个表单字段中,而不是通过表单的隐藏字段自动回传给服务器。
2) 服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。
3) 密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。
2、 实践
1) 整个程序包含三个组件:check_code.html、CheckCodeServlet.java和LogonFormServlet.java。
2) check_code.html是引用验证码图片的FORM表单页面,CheckCodeServlet.java是用于产生带有随机验证码图片的Servlet程序,LogonFormServlet.java则是负责处理FORM表单请求的Servlet程序。
3、 实例
login.html
<img src=”servlet/checkCode”>嵌入一个图片
CheckCodeServlet:产生验证码 对象session
提交给表单验证的LoginFormServlet:验证输入的验证码,和图片中显示的验证码是否一致
package com.csdn.session;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@SuppressWarnings("serial")
public class CheckCodeServlet extends HttpServlet {
public CheckCodeServlet() {
super();
}
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
//设置图片的大小
private static int WIDTH=60;
private static int HEIGHT=20;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("image/jpeg");
ServletOutputStream out=response.getOutputStream();
HttpSession session=request.getSession();
//产生验证码的图片
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Controll","no-cache");
response.setIntHeader("Expires", 0);
//背景
BufferedImage bi=new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);//画纸
Graphics g=bi.getGraphics();//画笔
drawBackground(g);
//随机产生验证码
char[] rands=generateCheckCode();
drawRands(g,rands);
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ImageIO.write(bi,"JPEG",bos);
byte[] buf=bos.toByteArray();//将bi对象里面的内容转换成了一个字节数
out.write(buf);
response.setContentLength(buf.length);
session.setAttribute("checkCode",new String(rands));
out.flush();
out.close();
}
//画字符
private void drawRands(Graphics g,char[] rands){
g.setColor(Color.black);
g.setFont(new Font(null,Font.ITALIC|Font.BOLD,18));//|是或运算
g.drawString(""+rands[0], 1, 17);
g.drawString(""+rands[1], 16, 18);
g.drawString(""+rands[2], 32, 16);
g.drawString(""+rands[3], 46, 17);
System.out.println(new String(rands));
}
//获得4位验证码
private char[] generateCheckCode(){
String chars="0123456789abcdefghijklmnopqrstuvwxyz";
char rands[]=new char[4];
for(int i=0;i<4;i++){
int random=(int)(Math.random()*36);
rands[i]=chars.charAt(random);
}
return rands;
}
private void drawBackground(Graphics g){
g.setColor(new Color(0xDCDC));
//画矩形框
g.fillRect(0, 0, WIDTH, HEIGHT);
for(int i=0;i<120;i++){
int x=(int)(Math.random()*WIDTH);
int y=(int)(Math.random()*HEIGHT);
int red=(int)(Math.random()*255);
int greed=(int)(Math.random()*255);
int blue=(int)(Math.random()*255);
g.setColor(new Color(red,greed,blue));//画笔颜色
//画椭圆
g.drawOval(x, y, 1, 0);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();*/
doGet(request,response);
}
public void init() throws ServletException {
// Put your code here
}
}
作业:验证码的验证