1. 程式人生 > >JavaWeb入門實戰—會話管理(Cookie&Session)

JavaWeb入門實戰—會話管理(Cookie&Session)

會話

什麼是會話?

會話可簡單理解為:使用者開一個瀏覽器,點選多個超連結,訪問伺服器多個web資源,然後關閉瀏覽器,整個過程稱之為一個會話。
會話過程中要解決的一些問題?
每個使用者在使用瀏覽器與伺服器進行會話的過程中,不可避免各自會產生一些資料,程式要想辦法為每個使用者儲存這些資料。
例如:使用者點選超連結通過一個servlet購買了一個商品,程式應該想辦法儲存使用者購買的商品,以便於使用者點結帳servlet時,結帳servlet可以得到使用者購買的商品為使用者結帳。

思考:使用者購買的商品儲存在request或servletContext中行不行?

不行,如果儲存在request物件中的宣告週期很短,一個請求完了物件就消失了;servletContext中儲存的是全域性應用資料,也不適合來儲存每個使用者的資料。

儲存會話資料的兩種技術
Cookie
Cookie是客戶端技術,程式把每個使用者的資料以cookie的形式寫給使用者各自的瀏覽器。當用戶使用瀏覽器再去訪問伺服器中的web資源時,就會帶著各自的資料去。這樣,web資源處理的就是使用者各自的資料了。
Session

Session是伺服器端技術,利用這個技術,伺服器在執行時可以為每一個使用者的瀏覽器建立一個其獨享的session物件,由於session為使用者瀏覽器獨享,所以使用者在訪問伺服器的web資源時,可以把各自的資料放在各自的session中,當用戶再去訪問伺服器中的其它web資源時,其它web資源再從使用者各自的session中取出資料為使用者服務。

Cookie API
javax.servlet.http.Cookie類用於建立一個Cookie,response介面中定義了一個addCookie方法,它用於在其響應頭中增加一個相應的Set-Cookie頭欄位。 同樣,request介面中也定義了一個getCookies方法,它用於獲取客戶端提交的Cookie。

Cookie API文件如下:


Cookie類的方法: 

  • public Cookie(String name,String value)
  • setValue與getValue方法 
  • setMaxAge與getMaxAge方法 (秒)
  • setPath與getPath方法
  • setDomain與getDomain方法
  • getName方法 

Cookie細節

  • 一個Cookie只能標識一種資訊,它至少含有一個標識該資訊的名稱(NAME)和設定值(VALUE)。 
  • 一個WEB站點可以給一個WEB瀏覽器傳送多個Cookie,一個WEB瀏覽器也可以儲存多個WEB站點提供的Cookie。
  • 瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB。
  • 如果建立了一個cookie,並將他傳送到瀏覽器,預設情況下它是一個會話級別的cookie(即儲存在瀏覽器的記憶體中),使用者退出瀏覽器之後即被刪除。若希望瀏覽器將該cookie儲存在磁碟上,則需要使用maxAge,並給出一個以秒為單位的時間。將最大時效設為0則是命令瀏覽器刪除該cookie。

注意,刪除cookie時,path必須一致,否則不會刪除。將Cookie的maxAge設定為0後不要忘了寫回Cookie。

如何向客戶端寫一個cookie
HttpServletResponse.addCookie(javax.servlet.http.Cookie)
注:每個伺服器只能存放20 cookie(稀有),瀏覽器端最多能存放300cookie,每個cookie的大小不能超過4Kb
伺服器如何獲取客戶端帶來的cookie
HttpServletRequest.getCookies() 
注:不同網站向同一個客戶端寫的cookie的名稱一致,可以通過cookie的path屬性進行區分
cookie的預設存活時間是會話範圍。

Cookie應用案例

1、顯示使用者上次訪問時間

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//記住使用者上次訪問的時間
public class CookieDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("您上次訪問的時間是:");
		//獲取客戶端提交的指定的cookie   lastAccessTime=321874983274329
		Cookie cookies[] = request.getCookies();//會獲取此路徑下的cookie  http://localhost:8080/day06/servlet/
		for(int i=0;cookies!=null&&i<cookies.length;i++){
			if(cookies[i].getName().equals("lastAccessTime")){
				//有上次訪問時間的cookie
				String value = cookies[i].getValue();//得到毫秒值
				Date date = new Date(Long.parseLong(value));
				out.print(date.toLocaleString());
				break;
			}
		}
		
		//把當前的時間寫給客戶端
		Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");
		cookie.setPath(request.getContextPath());// /day06
		cookie.setMaxAge(Integer.MAX_VALUE);//設定存活時間
		response.addCookie(cookie);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

刪除指定的Cookie,示例程式碼如下:
import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//刪除cookie:lastAccessTime
public class CookieDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//得到指定的cookie,設定它的age為0
		Cookie cookies[] = request.getCookies();
		for(int i=0;cookies!=null&&i<cookies.length;i++){
			if(cookies[i].getName().equals("lastAccessTime")){
				cookies[i].setMaxAge(0);
				cookies[i].setPath(request.getContextPath());//要與當時設定的路徑保持一致,否則可能刪除的不是同一個cookie
				response.addCookie(cookies[i]);//寫回客戶端
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

注意:沒有直接remove cookie的API,如果要刪除一個Cookie時,將該Cookie的maxAge設定為0,path必須一致,否則不會刪除。 最後不要忘了寫回Cookie。

2、記住使用者名稱

生成登陸介面程式碼:

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//生成登陸頁面
//讀取指定的cookie
public class CookieDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String username = "";
		String checked = "";
		//獲取指定的cookie,改變username和checked的值
		Cookie cookies[] = request.getCookies();
		for(int i=0;cookies!=null&&i<cookies.length;i++){
			Cookie cookie = cookies[i];
			if(MyConstant.USERNAME.equals(cookie.getName())){
				username = cookie.getValue();
				checked = "checked='checked'";
				break;
			}
		}
		
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("<html><head><title>登陸</title></head><body>");
		out.print("<form action='"+request.getContextPath()+"/servlet/CookieDemo4' method='post'>");
		out.print("使用者名稱:<input type='text' name='username' value='"+username+"'/><br/>");
		out.print("密碼:<input type='password' name='password' value=''/><br/>");
		out.print("記住使用者名稱:<input type='checkbox' name='remember' "+checked+"/><br/>");
		out.print("<input type='submit' value='登陸'/>");
		out.print("</form></body></html>");
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

登陸邏輯處理程式碼:
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//完成使用者登陸
//根據是否記錄使用者名稱來寫cookie
public class CookieDemo4 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String remember = request.getParameter("remember");
		String username = request.getParameter("username");
		if(remember==null){
			//不需要記住:刪除cookie  username=wzhting
			Cookie cookies[] = request.getCookies();
			for(int i=0;cookies!=null&&i<cookies.length;i++){
				Cookie c = cookies[i];
				if(MyConstant.USERNAME.equals(c.getName())){
					c.setMaxAge(0);
					c.setPath(request.getContextPath());
					response.addCookie(c);
					break;
				}
			}
		}else{
			//記住:寫cookie
			Cookie cookie = new Cookie(MyConstant.USERNAME,username);
			cookie.setMaxAge(Integer.MAX_VALUE);
			cookie.setPath(request.getContextPath());
			response.addCookie(cookie);
		}
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("登陸成功!歡迎您:"+username);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

Session
在WEB開發中,伺服器可以為每個使用者瀏覽器建立一個會話物件(session物件),注意:一個瀏覽器獨佔一個session物件(預設情況下)。因此,在需要儲存使用者資料時,伺服器程式可以把使用者資料寫到使用者瀏覽器獨佔的session中,當用戶使用瀏覽器訪問其它程式時,其它程式可以從使用者的session中取出該使用者的資料,為使用者服務。
Session和Cookie的主要區別在於:
  • Cookie是把使用者的資料寫給使用者的瀏覽器。
  • Session技術把使用者的資料寫到使用者獨佔的session中。
Session物件由伺服器建立,開發人員可以呼叫request物件的getSession方法得到session物件。

Session API文件如下:


Session原理

session技術利用了cookie技術,向客戶端寫了一個name為JSESSIONID,value為session物件的id 的Cookie物件。
Cookie的path:/xxx(Web應用的名稱) request.getContextPath()
Cookie的age:負數

思考:

如何實現多個IE瀏覽器共享同一session?應用:關掉IE後,再開IE,上次購買的商品還在。

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//http://192.168.1.251:8080/day06/servlet/SessionDemo1?name=wzhting
public class SessionDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String name = request.getParameter("name");
		HttpSession session = request.getSession();
		System.out.println(session.getId());
		session.setAttribute("p", name);
		//儲存cookie
		Cookie cookie = new Cookie("JSESSIONID",session.getId());
		cookie.setMaxAge(Integer.MAX_VALUE);
		cookie.setPath(request.getContextPath());
		response.addCookie(cookie);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

答案:我們手動儲存一下Session的Cookie物件即可。

獲取Session

HttpServletRequest介面中中定義了獲取Session的方法,如下:
 HttpSession getSession() 
          Returns the current session associated with this request, or if the request does not have a session, creates one. 
 HttpSession getSession(boolean create) 
          Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a new session. 
If create is false and the request has no valid HttpSession, this method returns null. 
To make sure the session is properly maintained, you must call this method before the response is committed. If the container is using cookies to maintain session integrity and is asked to create a new session when the response is committed, an IllegalStateException is thrown. 

注意:
關閉瀏覽器是結束一次會話。但是對於伺服器來講,並不會立刻銷燬記憶體中的session物件。預設的session的存活時間是30分鐘。

Session案例

1、使用Session完成簡單的購物車功能

商品列表Servlet程式碼:

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.cookie.app2.Book;
import com.itheima.cookie.app2.BookDb;
//顯示所有的商品
//提供購買連結
public class ShowAllProductsServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("<h1>本站有以下好書:</h1>");
		Map<String, Book> books = BookDb.getAllBooks();
		for(Map.Entry<String, Book> me:books.entrySet()){
			out.print(me.getValue().getName()+"  <a href='"+request.getContextPath()+"/servlet/BuyServlet?id="+me.getKey()+"'>購買</a><br/>");
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

購買的Servlet程式碼:
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.itheima.cookie.app2.Book;
import com.itheima.cookie.app2.BookDb;
//購買Servlet:把當前商品加入到購物車中
//購物車應在會話範圍
public class BuyServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		String id = request.getParameter("id");
		Book book = BookDb.findBookById(id);
		//將當前買的書加入到購物車
		HttpSession session = request.getSession();
		List<Book> cart = (List<Book>) session.getAttribute("cart");
		if(cart==null){
			//沒有購物車
			cart = new ArrayList<Book>();
			cart.add(book);
			session.setAttribute("cart", cart);
		}else{
			//有購物車
			cart.add(book);
		}
		out.print("<a href='/day06/servlet/ShowAllProductsServlet'>繼續購物</a><br/><a href='/day06/servlet/ShowCartServlet'>去結算</a>");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

檢視購物車Servlet程式碼:
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.itheima.cookie.app2.Book;

public class ShowCartServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("您購買了以下商品:");
		HttpSession session  = request.getSession();
		List<Book> cart = (List<Book>) session.getAttribute("cart");
		for(Book b:cart){
			out.print(b.getName()+"<br/>");
		}
		out.print("付賬");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

2、Session實現一次性校驗碼

一次性驗證碼的主要目的就是為了限制人們利用工具軟體來暴力猜測密碼。 
伺服器程式接收到表單資料後,首先判斷使用者是否填寫了正確的驗證碼,只有該驗證碼與伺服器端儲存的驗證碼匹配時,伺服器程式才開始正常的表單處理流程。 

生成動態驗證碼Servlet原始碼:

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.util.MD5Util;

public class ImageServlet extends HttpServlet {

	private static final int WIDTH = 120; 
	private static final int HEIGHT = 25;
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//不要快取
//		response.setHeader("Expires", "-1");
		response.setIntHeader("Expires", -1);
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		
//		BufferedImage  代表一副記憶體圖片
//		Graphics  代表畫筆
//		ImageIO   使用者輸出圖片
		
		//1、建立記憶體影象
		BufferedImage image  = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
		//2、得到屬於該影象的畫筆
		Graphics g = image.getGraphics();
		//3、設定畫筆顏色:畫邊框
		g.setColor(Color.RED);
		g.drawRect(0, 0, WIDTH, HEIGHT);//ctrl+shift+x變大寫   +y
//			畫背景
		g.setColor(Color.YELLOW);
		g.fillRect(1, 1, WIDTH-2, HEIGHT-2);
//			畫干擾線:9
		g.setColor(Color.GREEN);
		Random r = new Random();
		for(int i=0;i<9;i++)
			g.drawLine(r.nextInt(WIDTH), r.nextInt(HEIGHT), r.nextInt(WIDTH), r.nextInt(HEIGHT));
//			畫驗證碼:4(數字 隨機的)
		g.setColor(Color.RED);
		g.setFont(new Font("宋體", Font.BOLD|Font.ITALIC, 16));
		int x = 25;
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<4;i++){
			int num = r.nextInt(10);
			g.drawString(num+"", x, 15);
			x+=20;
			sb.append(num);
		}
		//將驗證碼放入session中
		String code = sb.toString();//1234
		//加密後放:md5
		code=MD5Util.encode(code);
		request.getSession().setAttribute("code", code);
		//4、輸出圖片
		ImageIO.write(image, "JPEG", response.getOutputStream());
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

登陸介面html程式碼:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>login.html</title>
	
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

  </head>
  
  <body>
    <form action="/day06/servlet/LoginServlet1" method="post">
    	使用者名稱:<input type="text" name="username"/><br/>
    	密碼:<input type="password" name="password"/><br/>
    	驗證碼:<input type="text" name="code"/><img src="/day06/servlet/ImageServlet"/><br/>
    	<input type="submit" value="登陸"/>
    </form>
  </body>
</html>

處理使用者登陸邏輯的Servlet程式碼:
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.itheima.session.app2.User;
import com.itheima.util.MD5Util;

public class LoginServlet1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//驗證使用者名稱和密碼是否正確(略)
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		//把當前登陸使用者放入session中
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String code = request.getParameter("code");//明文1234
		String scode = (String)request.getSession().getAttribute("code");//指紋jdskflkdsjfewoir
		if(!scode.equals(MD5Util.encode(code))){
			out.print("對不起!驗證碼不正確");
			return;
		}
		User u = new User();
		u.setUsername(username);
		u.setPassword(password);
		HttpSession session = request.getSession();
		session.setAttribute("user", u);
		//提示登陸成功,2秒後轉向主頁
		response.setHeader("Refresh", "2;URL=/day06/servlet/IndexServlet1");
		out.print("恭喜登陸成功!2秒後會自動轉向主頁");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

登陸成功頁面Servlet原始碼:

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.itheima.session.app2.User;

public class IndexServlet1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		User u = (User)session.getAttribute("user");
		out.print("歡迎您:"+u.getUsername()+".這是主頁");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

MD5加密工具類程式碼:

import java.security.MessageDigest;

import sun.misc.BASE64Encoder;

public class MD5Util {
	public static String encode(String value){
		try{
			MessageDigest md = MessageDigest.getInstance("md5");
			byte b[] = md.digest(value.getBytes());//按照MD5演算法拿到的資料指紋。不同資料的指紋不同
			//Base64編碼:把沒有對應字元的二進位制轉成可見的字元
			BASE64Encoder base64 = new BASE64Encoder();
			return base64.encode(b);
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
	public static void main(String[] args) {
		String s1 = "1";
		System.out.println(encode(s1));
	}
}

3、Session防止表單重複提交

表單頁面由servlet程式生成,servlet為每次產生的表單頁面分配一個唯一的隨機標識號,並在FORM表單的一個隱藏欄位中設定這個標識號,同時在當前使用者的Session域中儲存這個標識號。 
當用戶提交FORM表單時,負責處理表單提交的serlvet得到表單提交的標識號,並與session中儲存的標識號比較,如果相同則處理表單提交,處理完後清除當前使用者的Session域中儲存的標識號。
在下列情況下,伺服器程式將拒絕使用者提交的表單請求:

  • 儲存Session域中的表單標識號與表單提交的標識號不同
  • 當前使用者的Session中不存在表單標識號
  • 使用者提交的表單資料中沒有標識號欄位
生成表單介面的Servlet原始碼如下:
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.util.UUIDUtil;

public class ServletDemo0 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//生成頁面,設定hidden的value。往session中放一個
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		String id = UUIDUtil.genId();
		request.getSession().setAttribute("token", id);
		out.write("<form action='/day06/servlet/ServletDemo1' method='post'>"+
    	"使用者名稱:<input type='text' name='username'/><br/>"+
    	"<input type='hidden' name='token' value='"+id+"'/>"+
    	"<input type='submit' value='登陸'/></form>");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

處理表單請求的Servlet原始碼如下:
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ServletDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		String cToken = request.getParameter("token");//頁面提交過來的值
		HttpSession session = request.getSession();
		String sToken = (String) session.getAttribute("token");//session中放的值
		if(cToken.equals(sToken)){
			System.out.println(request.getParameter("username"));
			session.removeAttribute("token");//刪除
		}else{
			out.print("請勿重複提交");
			return;
		}
//		try {
//			Thread.sleep(2000);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

IE禁用Cookie後的session處理
有些時候可能客戶端禁用了Cookie,這個時候使用者購買的商品就會丟失了,怎麼解決呢?

解決方案:URL重寫
response. encodeRedirectURL(java.lang.String url) 

  • 用於對sendRedirect方法後的url地址進行重寫。
response. encodeURL(java.lang.String url)
  • 用於對錶單action和超連結的url地址進行重寫 

相關推薦

JavaWeb入門實戰會話管理(Cookie&Session)

會話什麼是會話? 會話可簡單理解為:使用者開一個瀏覽器,點選多個超連結,訪問伺服器多個web資源,然後關閉瀏覽器,整個過程稱之為一個會話。 會話過程中要解決的一些問題?每個使用者在使用瀏覽器與伺服器進行會話的過程中,不可避免各自會產生一些資料,程式要想辦法為每個使用者儲存這

會話管理cookie&session

getpath 什麽 響應 setvalue 每次 瀏覽器中 一段 臺電 atm 1.會話技術:從瀏覽器開始訪問服務器,到關閉瀏覽器,這期間發生了許多次請求和響應,這個過程就叫做一次會話。2.問題:如何在一次會話中保存會話相關的數據。3.Cookie:將會話相關的數據保存到

【Web入門系列】初探會話管理-Cookie技術

瀏覽器 通過 存儲 管理 add servlet pat 丟失 setpath 特點 會話數據保存在瀏覽器客戶端。 Cookie技術核心 1、構造Cookie對象   Cookie(String name, String value) 2、設置cookie   #設置coo

JavaWeb狀態與會話管理Session

count = 0; ServletContext application = getServletContext(); Integer applicationCount = (Integer)application.getAttribute("count"); if(applicationCount !=

會話管理-cookiesession,禁用cookie的URL重寫,token的單態設計模式,異常丟擲,UUID,MD5,base64編碼

1、會話 會話可簡單理解為:使用者開一個瀏覽器,點選多個超連結,訪問伺服器多個web資源,然後關閉瀏覽器,整個過程稱之為一個會話。 會話過程中要解決的一些問題? 每個使用者在使用瀏覽器與伺服器進行會話的過程中,不可避免各自會產生一些資料,程式要想辦法為每個使用者儲存這些資

會話管理——cookiesession技術

存在 span str jsession 代碼 tco 2.3 cin cell 1 Cookie技術 1.1 Cookie技術特點: 會話數據保存在瀏覽器客戶端 1.2 Cookie的API Cookie類: 保存會話數據 1)創建Cookie對象,用於保存會話

會話技術Cookie&Session

會話技術Cookie&Session 一、會話技術簡介 1.儲存客戶端的狀態 例如網站的購物系統,使用者將購買的商品資訊儲存到哪裡?因為Http協議是無狀態的,也就是說每個客戶訪問伺服器端資源時,伺服器並不知道該客戶端是誰,所以需要會話技術識別客戶端的狀

JavaWeb 之 JSP簡介及Cookie Session

## JSP的簡介 EL的表示式 ## **JSP的簡介**          1.先學習Servlet技術,為什麼還要學習JSP的技術呢?         * 缺點:讓你使用Servlet的技術動態生成的網頁?response.getWriter("<form ac

JavaEE複習回顧六: 會話技術Cookie && Session

Cookie 和 Session 會話技術,我找了幾篇部落格,另外結合自己的學習,寫了這篇回顧,後面如果有更深的理解,我再接著新增內容。 相關部落格地址: 目錄 一、會話技術簡介 1.1、儲存

Shiro在Spring的會話管理session

會話管理 在shiro裡面可以發現所有的使用者的會話資訊都會由Shiro來進行控制,那麼也就是說只要是與使用者有關的一切的處理資訊操作都可以通過Shiro取得,實際上可以取得的資訊可以有使用者名稱、主機名稱等等,這所有的資訊都可以通過Subject介面取得。

會話管理session技術

        上一節我們總結了cookie技術,這節主要總結一下session技術。1. session物件        在web開發中,伺服器可以為每個使用者瀏覽器建立一個會話物件(session物件),注意:一個瀏覽器獨佔一個session物件(預設情況下)。因此,在

在前後端分離的專案中,後臺使用shiro框架時,怎樣使用它的會話管理系統(session),從而實現許可權控制

在前後端分離的專案中,ajax跨域和儲存使用者資訊是其中的重點和難點。 如果在後臺使用shiro框架來進行許可權控制,就需要用到cookie+session的模式來儲存使用者的資訊。 在前一篇文章《在前後端分離的專案中,ajax跨域請求怎樣附帶cookie》中,我具體寫了怎

JavaWeb入門實戰—JDBC

JDBC簡介 JDBC全稱為:Java Data Base Connectivity(java資料庫連線),它主要由介面組成。 組成JDBC的2個包:  java.sql  javax.sql 開發JDBC應用需要以上2個包的支援外,還需要匯入相應JDBC的資料庫實現(即資

javaweb會話管理和儲存會話資料的兩種技術(CookieSession

會話: 什麼是會話? •會話可簡單理解為:使用者開一個瀏覽器,點選多個超連結,訪問伺服器多個web資源,然後關閉瀏覽器,整個過程稱之為一個會話。 會話過程中要解決的一些問題? •每個使用者與伺服器進行互動的過程中,各自會有一些資料,程式要想辦法儲存每個使用者的

Cookie & Session會話管理與控制】

有效期 unset font 重置 也有 姓名 本地 tro 讀取 用現實生活 類比Cookie 和 Session : 兩個關於開會的故事: 在幾十年前人們開會的時候,都需要帶上一個參會證。這個參會證上有這個人的職務、姓名、單位、照片等信息。在開會的時候,會議安保人員

JavaWeb學習筆記五 會話技術Cookie&Session

function for type getwriter 信息 web資源 案例 utf-8 template 什麽是會話技術? 例如網站的購物系統,用戶將購買的商品信息存儲到哪裏?因為Http協議是無狀態的,也就是說每個客戶訪問服務器端資源時,服務器並不知道該客戶端是誰,所

javaweb學習總結(十一)——使用Cookie進行會話管理(轉)

緩存 利用 iter() 自然 web har oca main end 一、會話的概念   會話可簡單理解為:用戶開一個瀏覽器,點擊多個超鏈接,訪問服務器多個web資源,然後關閉瀏覽器,整個過程稱之為一個會話。  有狀態會話:一個同學來過教室,下次再來教室,我們會知道這個

JavaWeb——會話技術Cookie & Session

on() col 路徑 時間 blog 持久化 date timeout pat 會話技術 因為Http協議是無狀態的,也就是說每個客戶訪問服務器端資源時,服務器並不知道該客戶端是誰,所以需要會話技術識別客戶端的狀態。會話技術是幫助服務器記住客戶端狀態(區分不同的客戶端)

【Web入門系列】初探會話管理-Session

特點 會話資料儲存在伺服器端。 Session技術核心 1、建立或得到session物件   HttpSession getSession()     HttpSession getSession(boolean create)   2、設定session物

會話(狀態)管理CookieSession(一)

會話(狀態)管理Cookie與Session(一) 目錄 什麼是會話? 儲存會話狀態的兩種技術 Cookie應用 a.Cookie執行原理 b.建立Cookie 什麼是會話 會話可以簡單的理解為:使用者開啟瀏覽器訪問了多個資源,然後關閉瀏覽器。整個過程稱之