一、利用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
}
}
作業:驗證碼的驗證