Java Cookie和Session

来源:https://www.cnblogs.com/f-ck-need-u/archive/2018/01/21/8322445.html
-Advertisement-
Play Games

1.會話技術簡介 http協議是無狀態的,因此對於服務端來說,當它接收到客戶端的http請求時,無法識別這個請求來源於哪個客戶端。無狀態的協議有優點也有缺點,但對於需要識別客戶端甚至是需要記住客戶端的業務來說,應當要讓http協議"有狀態"。 需要記住客戶端的業務種類非常多。例如登陸系統,在一個頁面 ...


1.會話技術簡介

http協議是無狀態的,因此對於服務端來說,當它接收到客戶端的http請求時,無法識別這個請求來源於哪個客戶端。無狀態的協議有優點也有缺點,但對於需要識別客戶端甚至是需要記住客戶端的業務來說,應當要讓http協議"有狀態"。

需要記住客戶端的業務種類非常多。例如登陸系統,在一個頁面登錄後,新打開一個該網站頁面,應當也保持登錄狀態。再例如購物車系統,某用戶添加商品1後應當保證他還能繼續添加商品2,在結算時能夠讀取購物車中的所有商品。

如何讓服務端記住客戶端?目前使用最多的是cookie和session兩種會話技術。

  • 1.Cookie:數據存儲在客戶端本地,減少伺服器端的存儲的壓力,安全性不好,客戶端可以清除cookie。
  • 2.Session:將數據存儲到伺服器端,安全性相對好,會增加伺服器的壓力。

Cookie技術是將用戶的數據存儲到客戶端的技術,它的作用是為了讓服務端根據每個客戶端持有的cookie來區分不同客戶端。

cookie由cookie name、具有唯一性的cookie value以及一些屬性(path、expires、domain等)構成,其中value是區分客戶端的唯一依據。

Cookie的原理為:服務端在接收到客戶端首次發送的請求後,服務端在響應首部中加入"set-cookie"欄位發送給客戶端;客戶端接收響應後,將cookie信息存儲到記憶體中(如果設置了MaxAge屬性,則存儲到磁碟中);因為cookie數據在瀏覽器的記憶體中,因此無論是哪個頁面,客戶端再次向服務端發送請求時都能獲取該cookie信息,併在請求首部中加入"cookie"欄位發送給服務端;服務端藉此就可以識別客戶端,並從cookie中找到該客戶端的信息。

使用Cookie需要解決的兩個問題:

  • (1).服務端怎樣將一個Cookie發送到客戶端。
  • (2).服務端怎樣接受客戶端攜帶的Cookie。

設置Cookie涉及的幾個常用方法為:

  • Cookie(String cookie_name,String cookie_value):構造一個Cookie對象。
  • setPath(uri):當訪問屬於該uri下的路徑(包括子路徑)時,該cookie都生效,例如setPath("/Cookie"),當本機使用http://localhost/Cookie/servlet1http://localhost/Cookie/servlet2訪問時,都擁有該Cookie。
  • setMaxAge(int second):設置該屬性時,cookie將持久化保存到客戶端的磁碟中,保存時間為second秒。如果cookie不具有該屬性,則cookie只會存放在記憶體中。
  • setDomain(String domain):設置Cookie生效的域範圍,例如cookie.setDomain(".foo.com");,這將對foo.com域下的所有主機都生效(如www.foo.com),但不包括子域(www.abc.foo.com)。

設置好Cookie後,需要使用response的方法addCookie(Cookie cookie)將cookie加入到響應首部中發送給客戶端。

例如,以下是名為CooikeDemo工程的一個servlet,該servlet的uri路徑為"/cookieservlet"。

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;

public class CookieServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("username","zhangsan");  //構造cookie對象
        cookie.setPath("/CookieDemo");       //設置cookie生效的uri範圍
        cookie.setMaxAge(10*60);             //設置cookie持久到磁碟的時間為10分鐘
        response.addCookie(cookie);          //在響應首部中加入set-cookie欄位併發送給客戶端
    }

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

該cookie將會在響應首部加入set-cookie欄位發送給客戶端:

當客戶端再次請求時,將在請求首部中加入cookie欄位。

需要註意的幾點:

  • (1).Cookie中不能存儲中文。
  • (2).如果不設置持久化時間,cookie會存儲在瀏覽器的記憶體中,瀏覽器關閉時cookie信息銷毀,這是會話級的cookie。如果設置持久化時間,cookie信息會被持久化到磁碟中,這是持久級別的cookie。持久化後的cookie不會隨瀏覽器關閉而失效,而是在有效時間內都有效。
  • (3).setPath()設置的生效路徑為目錄時,則cookie對該目錄和子目錄下的資源都生效,如果生效路徑為文件時,則只對該文件有效。例如:
    cookie.setPath("/webapp");  //代表訪問webapp應用中的任何資源都攜帶cookie
    cookie.setPath("/webapp/cookieservlet");  //代表訪問webapp中的cookieservlet時才攜帶cookie信息
    
  • (4).如果想要刪除當前還有效的cookie信息,可以使用同名同路徑的持久化時間為0的cookie進行覆蓋。這樣一來,每次客戶端接收到響應後cookie就立即失效,也就無法攜帶cookie請求服務端。例如刪除上面示例的cookie信息
    Cookie cookie = new Cookie("username","zhangsan");
    cookie.setPath("/CookieDemo");
    cookie.setMaxAge(0);
    response.addCookie(cookie);
    

如前面的圖中所示,客戶端的cookie信息是以請求頭的方式發送到伺服器端的。因此服務端要獲取cookie信息,需要使用request對象中的方法getCookies()。這時唯一的獲取cookie的方法,它返回的是Cookie數組集合,因此需要遍歷該數組才能獲取指定名稱的cookie。

例如,獲取cookie name為"username"的cookie。

Cookie[] cookies = request.getCookies();
if(cookies != null) {
    for (Cookie coo : cookies) {
        String cookie_name = coo.getName();
        if (cookie_name.equals("username")) {
            String cookie_value = coo.getValue();
            System.out.println(cookie_name+":"+cookie_value);
        }
    }
}

3.Session技術

從打開一個瀏覽器訪問某個站點,到關閉這個瀏覽器的整個過程(釋放瀏覽器記憶體),成為一次會話。除了Cookie技術可以讓服務端在一次會話過程中記住客戶端,Session技術也可以達到這樣的目的。

Session技術將數據存儲在伺服器端,它會為每個客戶端都創建一塊記憶體空間存儲客戶端數據,併為客戶端分配一個存儲在cookie中的JSESSIONID,客戶端需要每次都攜帶一個這個ID,伺服器通過這個ID可以找到屬於該客戶端的記憶體空間。由於這個標識ID是藉助Cookie存儲的唯一性標識JSESSIONID,因此Session是基於Cookie來實現的。

Session的原理:服務端接收到某客戶端首次發送的請求後,為此客戶端生成一個session,並分配一段屬於該session的緩衝區,同時將該session配對的標識號JSESSIONID作為cookie的name添加到響應首部中返回給客戶端;客戶端下次訪問時,請求首部中將攜帶該JSESSIONID,服務端將根據該JSESSIONID尋找與之配對的session,如果能找到對應的session,則直接操作該session資源,否則將重新為此JSESSIONID分配一個session和對應的緩衝區。

使用Session技術需要解決如下三個問題:

  • (1).怎樣獲得屬於某客戶端的session對象(記憶體區域)?
  • (2).怎樣向session中存取數據?
  • (3).session對象的生命周期?

3.1 獲得Session對象

服務端通過客戶端發送cookie中的JSESSIONID區分客戶端,可以通過請求包中的這個信息來獲取該客戶端相關的session信息。

HttpSession session = request.getSession();

此方法有兩個作用:

  • (1).從cookie中獲取JSESSIONID,並尋找是否存在該ID對應的session對象。如果存在,則獲取該session對象。
  • (2).如果該客戶端沒有發送JSESSIONID或JSESSIONID和服務端記錄的ID值不匹配,則為該JSESSIONID重新分配一個session對象。

實際上就是根據JSESSIONID判斷該客戶端是否在伺服器上已經存在session了,有則用之,無則分配之。

3.2 向session中存取數據(session也是一個域對象)

session也是一個域對象,session域的作用範圍是整個session,可以對客戶端的多次請求生效。該範圍小於context域(即application域),大於request域(只在一次請求內有效)。

作為域對象,session對象也同樣具有如下三個方法:

session.setAttribute(String name,Object obj);
session.getAttribute(String name);
session.removeAttribute(String name);

此外,可以通過session對象的getId()方法獲取到該session的JSESSIONID值。

3.3 Session對象的生命周期

  • 創建:第一次執行request.getSession()時創建。當客戶端訪問帶有getSession()方法的servlet時會執行該方法並創建session,訪問jsp頁面也會,因為jsp預設設置session=true會創建session。但訪問靜態資源(html/pic)等不會,因為輸出這些靜態數據的預設servlet不執行getSession()。
  • 銷毀:
    • 1.伺服器(非正常)關閉時。
    • 2.session過期/失效(預設30分鐘,這個預設時間可以在web.xml中修改)。
      <session-config>
        <session-timeout>30</session-timeout>
      </session-config>
      
      需要註意的是失效時間的起算點,即從何時開始計算30分鐘?從不操作伺服器端的資源開始計時(即從最近一次讀取session數據開始)。
    • 3.手動銷毀session:session.invalidate();

也就是說,客戶端在一次會話中任何資源都共用一個session對象。

問題:瀏覽器關閉,session就銷毀了嗎?
不對,session存儲在服務端,和客戶端沒多大關係,只要客戶端沒有操作session,等一段時間後,session自動銷毀。
但是,關閉瀏覽器後,cookie中的JSESSIONID就丟失了,也就無法再找到對應的session數據。可以在發送session給客戶端前將jsessionid當成cookie的屬性並配置cookie的持久化時間持久化到客戶端磁碟,這樣再次打開瀏覽器時jsessionid就不會丟失。代碼大致如下:

HttpSession session = request.getSession();
session.setAttribute("username","Tom");
String id = session.getId();                  //獲取JSESSIONID值
Cookie cookie = new Cookie("JSESSIONID",id);  //"JSESSIONID"為固定值
cookie.setPath("/CookieDemo");
cookie.setMaxAge(12*60*60);   //JSESSIONID持久化保存12小時
response.addCookie(cookie);

response.getWriter().write("JSESSIONID:"+id);
System.out.println(session.getAttribute("username"));

 

註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 背景 我相信很多朋友跟我一樣,初次聽到什麼 Flux , Redux , Vuex , 狀態管理 的時候是一臉懵逼的。因為在外面之前前端大部分開發的時候,根本沒有那麼多的概念。自從ReactJS火爆後,什麼 Flux, Redux,React全家桶 是一套一套接踵而來。搞的很多開發者甚是頭大。所謂的 ...
  • /** * Created by admin on 2017/8/19. */ // import Vue from 'vue' // import axios from './HTTP.js' // Vue.use(axios) import * as DB from './DBDATA.js' ... ...
  • 前臺: 支持四套模版, 可以在後臺切換 系統介紹: 1.網站後臺採用主流的 SSM 框架 jsp JSTL,網站後臺採用freemaker靜態化模版引擎生成html 2.因為是生成的html,所以訪問速度快,輕便,對伺服器負擔小 3.網站前端採用主流的響應式佈局,同一頁面同時支持PC、平板、手機(三 ...
  • 因為是開發階段,我需要在本地調試,而微信開發需要配置功能變數名稱,這樣natapp.cn就有了用武之地,應該說natapp就是為此而生的。 natapp.cn是什麼 這是一個內網映射的網站,支持微信公眾號、小程式本地開發調試,具體詳情請到官網去瞭解:https://natapp.cn/ 雖然官網已經有配置教 ...
  • C/S又稱Client/Server或客戶/伺服器模式。伺服器通常採用高性能的PC、工作站或小型機,並採用大型資料庫系統,如Oracle、Sybase、Informix或 SQL Server。客戶端需要安裝專用的客戶端軟體。 B/S是Brower/Server的縮寫,客戶機上只要安裝一個瀏覽器(B ...
  • Django中模型(二) 三、定義模型 1、模型、屬性、表、欄位間的關係: 一個模型類在資料庫中對應一張表;在模型類中定義的屬性,對應該模型對照表中的欄位。 2、定義屬性 A、概述 ·django根據屬性的類型確定以下信息 ·當前選擇的資料庫支持欄位的類型 ·渲染管理表單時使用的預設html控制項 · ...
  • B站是目前本人看到的最好的免費學習Python的網站 黑馬程式員- https://space.bilibili.com/37974444?spm_id_from=333.338.viewbox_report.6#/ B站上找老男孩Linux 教育視頻 關註黑馬程式員官方微信可下載近70G的Pyth ...
  • #for 和 while #for用來迭代處理,什麼叫迭代?你就當沒看到這個詞,for是把一堆玩意做一個一個加工用的,比如吃一袋花生,得一個一個剝吧,就是這意思 a = 'abcde' #每個字母當做一個花生,a是一袋子 for i in a: #從袋子裡面一個一個拿花生,拿出的每一個花生都起名叫小 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...