Session 和 cookie
一、Cookie
Cookie是什麼呢?Cookie,有時也用其複數形式 Cookies。類型為“小型文本檔案”,是某些網站為了辨識使用者身份,進行Session跟蹤而儲存在使用者本地終端上的資料(通常經過加密),由使用者用戶端計算機暫時或永久儲存的資訊-----來自維基百科。用一句話來講,就是存儲在用戶端伺服器上的資料,是由網景公司(也就是這個公司發明了浏覽器哦)發明的一種網絡會話狀态跟蹤技術。
1.1 會話
可能有人會提出疑問,網絡會話狀态又是什麼呢?首先我們要弄清網絡會話,會話,字面意思上就是一次交談,就用戶端A和服務端B就可以類比成兩個人小A和小B,一次會話就是AB之間的一次對話。如果用專業點的術語來講的話(●’◡’●),就是一次請求與響應。
在一次請求和響應中,肯定是有資料傳遞的,是以這時,就需要會話狀态跟蹤 來檢視資料在這次會話中的狀态,但是在網絡層的Http協定是無狀态的。
小插曲:無狀态是什麼?
也就是當我們的小A和小B在進行通話完畢後,他們第二次又見面了,但是他們對上一次的會話一點都不記得了(當然現實中不太可能啦),也就是相當于丢失了在上次會話中的狀态。
是以Cookie是由伺服器并存放在用戶端的一種資訊載體,存有這次會話的資訊,隻要Cookie沒有被清空,或者Cookie沒有失效,那麼會話狀态就是有效的。
1.2 Cookie在會話中的狀态
使用者在第一次請求後,由伺服器生成Cookie,并将其封裝到響應頭中,以響應的方式發送給用戶端,用戶端接受到這個請求後,儲存到用戶端。當用戶端再次發同類請求,那麼就會将Cookie攜帶上,以此作為憑證,來通路服務端作校驗。
1.3 Cookie本質
其實Cookie本質是多個Key-value鍵值對而已。但是針對不同的浏覽器,Cookie的儲存方式和儲存的位置都不一樣。
1.4 JavaEE下的Cookie
常用API
public class ServletDome extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException{
//利用唯一的構造函數狗雜Cookie
Cookie cookie=new Cookie("key","value");
//綁定這個Cookie是在哪個資源路徑下的,注意,這裡必須要綁定項目名稱
cookie.setPath(req.getContextPath()+"/a/b");
/**
* @target 設定這個Cookie的過時時間,機關是秒
* 如果時間大于0則需要将這個cookie存入外存中
* 時間小于就是存在記憶體(緩存中),關閉頁面就消失
* 時間等于0就是一旦産生就馬上失效
*/
cookie.setMaxAge(60*60);
//在HTTP Servlet Response中添加這個Cookie鍵值對
resp.addCookie(cookie);
}
}
public class ServletGetCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//擷取請求中的Cookie資訊
Cookie[] cookies=req.getCookies();
for(Cookie c:cookies){
System.out.println(c.getName()+"======="+c.getValue());
}
}
}
1.5 域屬性空間
總的來說一共有三個域屬性空間,在使用時優先肯定是使用小的,友善于保障資料的安全性,由大到小依次是:
- ServletContext:
是屬于域的,可以完成跨會話的共享資料
-
HttpSession
置入其中的域屬性是會話範圍的,可以完成同類請求下的通路共享資料
-
HttpServletRequest
置入其實中的域屬性隻有在目前的請求路徑下,可以完成跨Servlet共享資料
二、Session
2.1 Session
Session也是一種會話狀态跟蹤技術。當然前面所講述的Cookie也是同樣目的的技術。但是兩者并不沖突,通常是将兩者進行混合使用,因為Session是将相關資料儲存在伺服器端的,并不是在用戶端。
Session是整個Web應用中所使用的,是以javax.servlet.http.HttpSession的接口對象的形式出現。
2.2 域屬性空間
Session,簡稱為域。其實也就是HttpSession,是可以進行跨請求的。
其中有三個方法可以對其資料進行寫和讀:
-
setAttribute(Stirng name,Object value)
用于存放資料
-
getAttribute(String name)
用于擷取Value
-
removeAttribute(String name)
用于删除
2.3 Sesion的具體使用
public class SomeServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//擷取使用者送出的參數
String username=request.getParameter("username");
//将參數放入request域
request.setAttribute("user",username);
//擷取Session對象
HttpSession session=request.getSession(false);
//在session域中寫入屬性
session.setAttribute("username",username);
response.getWriter().print("SomeServlet: "+username);
}
}
public class OtherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String user=req.getParameter("user");
//擷取Session
HttpSession session=req.getSession(false);
//從Session中讀取指定屬性
String username=null;
if (session!=null){
username= (String) session.getAttribute("username");
}
PrintWriter out=resp.getWriter();
out.print("OtherServlet:user: "+user);
out.print("OtherServlet:username: "+username);
}
}
2.4 Session工作原理
在系統中會對每一個會話維護一個Session會話,這裡擴充下前面的域屬性空間,其中,跨域,是指可以跨越不同的伺服器;跨請求,是指可以跨越不同的工程;跨Servlet是指可以跨越不同的具體資源。(HttpSession的具體實作類是在Tomcat中的)
-
寫入Session清單
伺服器對目前的Session是以Map管理的,也就是Session清單
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-mltw3ewn-1588090079713)(D:\App\Typora\resources\md-image\Session和Cookie\image-20200428222809253.png)]
key是以32位長度的随機串,被稱作JSessionID
value是Session對象的引用
當使用者第一次送出請求時,服務端Servlet中執行request.getSession()後,會自動生成一個Map.Entry對象,然後存入key-value;
-
伺服器生成并發送Cookie
在服務端存入了相應的Session資訊後,系統還會自動将“JSESSIONID”作為key,sessionid作為value,放到response的頭中去,并存入用戶端,這個也就是Cookie。
-
用戶端接受并發送Cookie
用戶端将接受到的JSESSIONID這個Cookie放入緩存中,當使用者第二次通路的時候,會将緩存中這個Cookie,伴随着請求頭的頭部資訊,一起發送出去。
2.5 Session的失效
我們在平時會發現,當我們長時間不去登入一個網站後,本來會自動顯示的賬号提示資訊會消失不見(這個資訊也是由session存放的)。其實這個因為Session失效了。那麼什麼是失效呢?
首先,我們可以在web.xml中設定session的逾時時間(默默提一句,為什麼是在web.xml中設定,因為HttpSession的具體實作類是在Tomcat中實作的)
<session-config>
<!--以分鐘為機關-->
<session-timeout>10</session-timeout>
</session-config>
或者在Java代碼中,拿到session對象調用invalidate方法
那麼什麼時候會失效呢?我們把頁面關了算不算以及失效了呢?在平時我們總是這樣認為,但其實并不是。在上面我們已經知道session的真正引用會存儲在服務端,是以當我們沒用Cookie這個憑證時,我們直接拿那32位的門票進去也可以擷取到那個Session的引用。是以隻有當我們等服務端的session真正失效後才總算是真正安全的。
2.6 重定向和轉發的番外
當我們在禁用Cookie後,上面提到了,我們扔可以通過JSeesionID來擷取到Session對象。但是當我們重定向時禁掉Cookie時怎麼擷取那個重定向後的資料呢?我們可以encode來自動通過上面的方法來通路重定向後的禁用掉Cookie的網站
String url=req.getContextPath()+"someSevlet";
url=resp.encodeRedirectURL(url);
resp.sendRedirect(url);
轉發也是如此,隻是調用的函數不同罷了:
String url=req.getContextPath()+"someSevlet";
url=resp.encodeURL(url);
resp.sendRedirect(url);
)+"someSevlet";
url=resp.encodeRedirectURL(url);
resp.sendRedirect(url);
轉發也是如此,隻是調用的函數不同罷了:
String url=req.getContextPath()+"someSevlet";
url=resp.encodeURL(url);
resp.sendRedirect(url);