自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Cookie、Session和Application都是些什么神?

新聞
該加密機(jī)制中最重要的部分為算法與密鑰。由于MD1算法的不可逆性,即使用戶知道了賬號與加密后的字符串,也不可能解密得到密鑰。因此,只要保管好密鑰與算法,該機(jī)制就是安全的。

前言

一直想寫一篇關(guān)于cookie和session的博客,由于種種原因,一直沒有整理,這不,今天還就遇到問題了,之前雖然會,但是好久沒用又給忘了,結(jié)果還得查資料。是時候填坑了,閑話少說,開干。

application

Application用于保存所有用戶的公共的數(shù)據(jù)信息,在這只是提一下,不過多解釋。

下面我主要解說cookie和session,不過在解說之前有必要讓大家先了解一下HTTP協(xié)議和會話跟蹤。

HTTP協(xié)議

協(xié)議是指計(jì)算機(jī)通信網(wǎng)絡(luò)中兩臺計(jì)算機(jī)之間進(jìn)行通信所必須共同遵守的規(guī)定或規(guī)則

HTTP協(xié)議工作于客戶端-服務(wù)端架構(gòu)上。瀏覽器作為HTTP客戶端通過URL向HTTP服務(wù)端即WEB服務(wù)器發(fā)送所有請求。再通俗點(diǎn)講,Http協(xié)議基本是有一個request/response模型也就是請求/響應(yīng)模型的,通俗講也就是“一問一答”的模式,瀏覽器向服務(wù)器發(fā)起request請求,這就是“問”;服務(wù)器收到請求后,返回response響應(yīng),這就是“答”。

需要強(qiáng)調(diào)的是HTTP是無連接并且是無狀態(tài)的

無連接:無連接的含義是限制每次連接只處理一個請求。服務(wù)器處理完客戶的請求,并收到客戶的應(yīng)答后,即斷開連接。采用這種方式可以節(jié)省傳輸時間。

無狀態(tài):無狀態(tài)是指協(xié)議對于事務(wù)處理沒有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。

HTTP協(xié)議是無狀態(tài)的協(xié)議。一旦數(shù)據(jù)交換完畢,客戶端與服務(wù)器端的連接就會關(guān)閉,再次交換數(shù)據(jù)需要建立新的連接。這就意味著服務(wù)器無法從連接上跟蹤會話。

會話跟蹤

在計(jì)算機(jī)術(shù)語中,會話是指一個終端用戶與交互系統(tǒng)進(jìn)行通訊的過程,比如從輸入賬戶密碼進(jìn)入操作系統(tǒng)到退出操作系統(tǒng)就是一個會話過程。會話較多用于網(wǎng)絡(luò)上,TCP的三次握手就創(chuàng)建了一個會話,TCP關(guān)閉連接就是關(guān)閉會話。

可能這些官方的話有些新手朋友看了不理解,沒關(guān)系,我再通俗點(diǎn),假如你就是用戶,你的電腦就是服務(wù)器,此時你想訪問我的博客園,我的博客園網(wǎng)址是https://www.cnblogs.com/zyx110/,然后你把我的博客園地址復(fù)制粘貼到了瀏覽器頁面的地址欄里,敲一下回車鍵,從你復(fù)制粘貼網(wǎng)址到敲擊回車鍵這個過程就是客戶端向服務(wù)器發(fā)送一個請求(request),等你敲擊過回車鍵后,你發(fā)現(xiàn)你的瀏覽器頁面跳轉(zhuǎn)到了泰斗賢若如的博客園,這個過程就是服務(wù)器給客戶端的一個響應(yīng)(response),再聯(lián)想上面說到的HTTP的無連接和無狀態(tài),客戶端和服務(wù)器之間只有一次聯(lián)系,而且“說了下句忘了上句”,還有就是這只是客戶端和服務(wù)器端間的聯(lián)系,瀏覽器的請求(request)與請求之間是沒有關(guān)系的。但是我們想要開發(fā)Web應(yīng)用,就應(yīng)該讓這些請求之間有關(guān)系,這就需要我們在多個request請求之間創(chuàng)建一些聯(lián)系,這就是會話(session),會話簡單點(diǎn)講就是“要想順利交談,需要說了下句想起來上句”,多次HTTP連接間維護(hù)用戶與同一用戶發(fā)出的不同請求之間關(guān)聯(lián)的情況稱為維護(hù)一個會話,所以這些建立聯(lián)系的request請求是屬于某個(會話)session的。

再舉個例子吧,可能有些朋友看了上面這些還有點(diǎn)猶豫,不要緊,慢慢理解,理論上,一個用戶的所有請求操作都應(yīng)該屬于同一個會話,而另一個用戶的所有請求操作則應(yīng)該屬于另一個會話,二者不能混淆。例如,你是用戶,你在淘寶購買的任何商品都應(yīng)該放在你的購物車內(nèi),不管你是什么時間購買的,這都是屬于同一個會話的,不能放入用戶B或用戶C的購物車內(nèi),這不屬于同一個會話。而Web應(yīng)用程序是使用HTTP協(xié)議傳輸數(shù)據(jù)的。HTTP協(xié)議是無連接無狀態(tài)的協(xié)議。一旦數(shù)據(jù)交換完畢,客戶端與服務(wù)器端的連接就會關(guān)閉,再次交換數(shù)據(jù)需要建立新的連接。這就意味著服務(wù)器無法從連接上跟蹤會話。即用戶A購買了一件商品放入購物車內(nèi),當(dāng)再次購買商品時服務(wù)器已經(jīng)無法判斷該購買行為是屬于用戶A的會話還是用戶B的會話了。要跟蹤該會話,必須引入一種機(jī)制。

Cookie就是這樣的一種機(jī)制。它可以彌補(bǔ)HTTP協(xié)議無狀態(tài)的不足。在Session出現(xiàn)之前,基本上所有的網(wǎng)站都采用Cookie來跟蹤會話。

會話(Session)跟蹤是Web程序中常用的技術(shù),用來跟蹤用戶的整個會話。常用的會話跟蹤技術(shù)是Cookie與Session。Cookie通過在客戶端記錄信息確定用戶身份,Session通過*在服務(wù)器端記錄信息確定用戶身份*。

cookie

由于HTTP是一種無狀態(tài)的協(xié)議,服務(wù)器單從網(wǎng)絡(luò)連接上無從知道客戶身份。用戶A購買了一件商品放入購物車內(nèi),當(dāng)再次購買商品時服務(wù)器已經(jīng)無法判斷該購買行為是屬于用戶A的會話還是用戶B的會話了。怎么辦呢?就給客戶端們頒發(fā)一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務(wù)器就能從通行證上確認(rèn)客戶身份了。這就是Cookie 的工作原理。

Cookie實(shí)際上是一小段的文本信息??蛻舳苏埱蠓?wù)器,如果服務(wù)器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個Cookie(通行證)??蛻舳藭袰ookie保存起來。

當(dāng)瀏覽器再請求該網(wǎng)站時,瀏覽器把請求的網(wǎng)址連同該Cookie一同提交給服務(wù)器。服務(wù)器檢查該Cookie,以此來辨認(rèn)用戶狀態(tài)。服務(wù)器還可以根據(jù)需要修改Cookie的內(nèi)容。

我們訪問瀏覽器的時候,瀏覽器會發(fā)送一個HTTP請求到服務(wù)器端;

服務(wù)器會發(fā)送一個HTTP響應(yīng)到客戶端,其中包括Sst-Cookie,意思就是瀏覽器建立一個cookie保存服務(wù)器指定的內(nèi)容,比如用戶信息和用戶操作信息;

瀏覽器保存好信息之后,下次我們再次訪問網(wǎng)站的時候,瀏覽器再發(fā)送HTTP請求到服務(wù)器端時都會攜帶之前保存的cookie;

服務(wù)器端會從收到的cookie中識別用戶身份,就能讓頁面為你提供專門屬于你的內(nèi)容了。

比如我們從網(wǎng)站的登陸界面中看到有記住用戶名這個選項(xiàng),你勾選了它以后,登錄成功,瀏覽器就會把你的信息放在cookie里,下次再訪問這個網(wǎng)站的時候,服務(wù)器就能根據(jù)收到的cookie識別出是你,幫你自動登陸,顯示專屬于你的內(nèi)容。

session

Session是另一種記錄客戶狀態(tài)的機(jī)制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務(wù)器上??蛻舳藶g覽器訪問服務(wù)器的時候,服務(wù)器把客戶端信息以某種形式記錄

在服務(wù)器上。這就是Session。客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態(tài)就可以了。

每個用戶訪問服務(wù)器都會建立一個session,那服務(wù)器是怎么標(biāo)識用戶的唯一身份呢?事實(shí)上,用戶與服務(wù)器建立連接的同時,服務(wù)器會自動為其分配一個SessionId。

思考兩個問題:

什么東西可以讓你每次請求都把SessionId自動帶到服務(wù)器呢?

顯然就是cookie了,如果你想為用戶建立一次會話,可以在用戶授權(quán)成功時給他一個唯一的cookie。當(dāng)一個用戶提交了表單時,瀏覽器會將用戶的SessionId自動附加在HTTP頭信息中,(這是瀏覽器的自動功能,用戶不會察覺到),當(dāng)服務(wù)器處理完這個表單后,將結(jié)果返回給SessionId

所對應(yīng)的用戶。試想,如果沒有 SessionId,當(dāng)有兩個用戶同時進(jìn)行注冊時,服務(wù)器怎樣才能知道到底是哪個用戶提交了哪個表單呢。

web開發(fā)發(fā)展至今,cookie和session的使用已經(jīng)出現(xiàn)了一些非常成熟的方案。在如今的市場或者企業(yè)里,一般有兩種存儲方式:

  • 存儲在服務(wù)器端:通過cookie存儲一個sessionid,然后具體的數(shù)據(jù)則是保存在session中。如果用戶已經(jīng)登錄,則服務(wù)器會在cookie中保存一個sessionid,下次再次請求的時候,會把該sessionid攜帶上來,服務(wù)器根據(jù)sessionid在session庫中獲取用戶的session數(shù)據(jù)。就能知道該用戶到底是誰,以及之前保存的一些狀態(tài)信息。這種專業(yè)術(shù)語叫做server side session。
  • 將session數(shù)據(jù)加密,然后存儲在cookie中。這種專業(yè)術(shù)語叫做client side session。flask采用的就是這種方式,但是也可以替換成其他形式。
  • 如何儲存需要的信息?

服務(wù)器通過SessionId作為key,讀寫到對應(yīng)的value,這就達(dá)到了保持會話信息的目的。

session的創(chuàng)建:

當(dāng)程序需要為某個客戶端的請求創(chuàng)建一個session時,服務(wù)器首先檢查這個客戶端的請求里是否已包含了sessionId,如果已包含則說明以前已經(jīng)為此客戶端創(chuàng)建過session,服務(wù)

器就按照sessionId把這個session檢索出來使用(檢索不到,會新建一個),如果客戶端請求不包含sessionId,則為此客戶端創(chuàng)建一個session并且生成一個與此session相關(guān)

聯(lián)的sessionId,sessionId的值是一個既不會重復(fù),又不容易被找到規(guī)律以仿造的字符串,這個sessionId將被在本次響應(yīng)中返回給客戶端保存。

禁用cookie:

如果客戶端禁用了cookie,通常有兩種方法實(shí)現(xiàn)session而不依賴cookie。

  1. URL重寫,就是把sessionId直接附加在URL路徑的后面。
  2. 表單隱藏字段。就是服務(wù)器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務(wù)器。比如:
  1. <form name="testform" action="/xxx" 
  2. <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764" 
  3. <input type="text" 
  4. </form> 

Session共享:

對于多網(wǎng)站(同一父域不同子域)單服務(wù)器,我們需要解決的就是來自不同網(wǎng)站之間SessionId的共享。由于域名不同(aaa.test.com和bbb.test.com),而SessionId又分別儲存

在各自的cookie中,因此服務(wù)器會認(rèn)為對于兩個子站的訪問,是來自不同的會話。解決的方法是通過修改cookies的域名為父域名達(dá)到cookie共享的目的,從而實(shí)現(xiàn)SessionId的共

享。帶來的弊端就是,子站間的cookie信息也同時被共享了。

cookie和session案例解析(記住我)

  1. package servlet;  
  2.  
  3. import domain.User 
  4.  
  5. import javax.servlet.ServletException; 
  6. import javax.servlet.annotation.WebServlet; 
  7. import javax.servlet.http.Cookie; 
  8. import javax.servlet.http.HttpServlet; 
  9. import javax.servlet.http.HttpServletRequest; 
  10. import javax.servlet.http.HttpServletResponse; 
  11. import java.io.IOException; 
  12. import java.util.List;  
  13.  
  14. /* 
  15. * 用戶登錄的Servlet 
  16. * */ 
  17. @WebServlet("/login"
  18. public class LoginServlet extends HttpServlet { 
  19. @Override 
  20. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  21.  
  22. req.setCharacterEncoding("utf-8"); 
  23. resp.setCharacterEncoding("utf-8");  
  24.  
  25. //接收數(shù)據(jù) 
  26. String username = req.getParameter("username"); 
  27. String password = req.getParameter("password"); 
  28. //從ServletContext域中獲得保存用戶信息集合 
  29. List<User> list = (List<User>) this.getServletContext().getAttribute("list"); 
  30. for (User user:list){ 
  31. //判斷用戶名是否正確 
  32. if (username.equals(user.getUsername())){ 
  33. //判斷密碼是否正確 
  34. if (password.equals(user.getPassword())){ 
  35. //用戶名密碼都正確 
  36. //登錄成功 
  37. //判斷記住用戶名復(fù)選框是否勾選 
  38. String remember = req.getParameter("remember"); 
  39. if ("true".equals(remember)){ 
  40. //完成記住用戶名的功能 
  41. Cookie cookie = new Cookie("username",username); 
  42. //設(shè)置有效路徑 
  43. cookie.setPath("/login.jsp");//設(shè)置此路徑后只能在login.jsp訪問cookie 
  44. //設(shè)置有效時間 
  45. cookie.setMaxAge(60*60*24); 
  46. //將cookie回寫到瀏覽器 
  47. resp.addCookie(cookie); 
  48. //將用戶的信息保存到Session中 
  49. req.getSession().setAttribute("user",user); 
  50. resp.sendRedirect("/success.jsp"); 
  51. return
  52. //登錄失敗 
  53. req.setAttribute("msg","用戶名或密碼錯誤!"); 
  54. req.getRequestDispatcher("/login.jsp").forward(req,resp);  
  55.  
  56. @Override 
  57. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  58. doGet(req, resp); 
  1. package utils; 
  2. import javax.servlet.http.Cookie; 
  3.  
  4. public class CookieUtils {  
  5. public static Cookie findCookie(Cookie[] cookies,String name){  
  6. if (cookies==null){  
  7. //說明客戶端沒有攜帶Cookie  
  8. return null 
  9. }else {  
  10. //說明客戶端攜帶Cookie  
  11. for (Cookie cookie:cookies){  
  12. if (name.equals(cookie.getName())){  
  13. return cookie;  
  14.  
  15.  
  16. return null 
  17. } 
  18.  

 

  1. <%@page import="utils.CookieUtils"%> 
  2. <%@ page language="java" contentType="text/html; charset=UTF-8" 
  3. pageEncoding="UTF-8"%> 
  4. <!DOCTYPE html> 
  5. <html> 
  6. <head> 
  7. <meta charset="UTF-8"
  8. <title>登錄頁面</title> 
  9. <link rel="stylesheet" href="./css/login.css"
  10. </head> 
  11. <body> 
  12. <div class="login"
  13. <div class="header"
  14. <h1> 
  15. <a href="/login.jsp">登錄</a> <a href="/regist.jsp">注冊</a> 
  16. </h1>  
  17.  
  18. </div> 
  19. <% 
  20. String username=""
  21. //獲得從客戶端攜帶過來的所有的Cookie 
  22. Cookie[] cookies = request.getCookies(); 
  23. // 從Cookie的數(shù)組中查找指定名稱的Cookie 
  24. Cookie cookie = CookieUtils.findCookie(cookies, "username"); 
  25. if(cookie != null){ 
  26. username = cookie.getValue(); 
  27.  
  28.  
  29. if(session.getAttribute("username")!=null){ 
  30. username = (String)session.getAttribute("username"); 
  31.  
  32.  
  33. String msg = ""
  34. if(request.getAttribute("msg")!=null){ 
  35. msg = (String)request.getAttribute("msg"); 
  36.  
  37.  
  38. %> 
  39. <h3><%=msg %></h3> 
  40. <form action="/login" method="post"
  41. <table
  42. <tr> 
  43. <td class="td1">用戶名</td> 
  44. <td><input type="text" class="input1" name="username" value="<%=username %>"></td> 
  45. </tr> 
  46. <tr> 
  47. <td class="td1">密碼</td> 
  48. <td><input type="password" class="input1" name="password"></td> 
  49. </tr> 
  50. <tr> 
  51. <td class="td1" colspan="2"
  52. <input type="checkbox" name="remember" value="true" checked="checked"> 記住用戶名</td> 
  53. </tr> 
  54. <tr> 
  55. <td colspan="2"
  56. <div class="btn-red"
  57. <input type="submit" value="登錄" id="login-btn"
  58. </div> 
  59. </td> 
  60. </tr> 
  61. </table 
  62.  
  63. </form> 
  64. </div> 
  65. </body> 
  66. </html> 

 

Cookie知識拓展

設(shè)置Cookie的所有屬性

除了name與value之外,Cookie還具有其他幾個常用的屬性。每個屬性對應(yīng)一個getter方法與一個setter方法。

Cookie常用屬性

Cookie的有效期

Cookie的maxAge決定著Cookie的有效期,單位為秒(Second)。Cookie中通過getMaxAge()方法與setMaxAge(int maxAge)方法來讀寫maxAge屬性。

如果maxAge屬性為正數(shù),則表示該Cookie會在maxAge秒之后自動失效。瀏覽器會將maxAge為正數(shù)的 Cookie持久化,即寫到對應(yīng)的Cookie文件中。無論客戶關(guān)閉了瀏覽器還是電腦,只要還在maxAge秒之前,登錄網(wǎng)站時該Cookie仍然有效。下面代碼中的Cookie信息將永遠(yuǎn)有效。

Cookie cookie = new Cookie("username","helloweenvsfei"); // 新建Cookie

cookie.setMaxAge(Integer.MAXVALUE); // 設(shè)置生命周期為MAXVALUE

response.addCookie(cookie); // 輸出到客戶端

如果maxAge為負(fù)數(shù),則表示該Cookie僅在本瀏覽器窗口以及本窗口打開的子窗口內(nèi)有效,關(guān)閉窗口后該 Cookie即失效。maxAge為負(fù)數(shù)的Cookie,為臨時性Cookie,不會被持久化,不會被寫到Cookie文件中。Cookie信息保存在瀏 覽器內(nèi)存中,因此關(guān)閉瀏覽器該Cookie就消失了。Cookie默認(rèn)的maxAge值為–1。

如果maxAge為0,則表示刪除該Cookie。Cookie機(jī)制沒有提供刪除Cookie的方法,因此通過設(shè)置該Cookie即時失效實(shí)現(xiàn)刪除Cookie的效果。失效的Cookie會被瀏覽器從Cookie文件或者內(nèi)存中刪除,

例如:

Cookie cookie = new Cookie("username","helloweenvsfei"); // 新建Cookie

cookie.setMaxAge(0); // 設(shè)置生命周期為0,不能為負(fù)數(shù)

response.addCookie(cookie); // 必須執(zhí)行這一句

response對象提供的Cookie操作方法只有一個添加操作add(Cookie cookie)。

要想修改Cookie只能使用一個同名的Cookie來覆蓋原來的Cookie,達(dá)到修改的目的。刪除時只需要把maxAge修改為0即可。

注意:從客戶端讀取Cookie時,包括maxAge在內(nèi)的其他屬性都是不可讀的,也不會被提交。瀏覽器提交Cookie時只會提交name與value屬性。maxAge屬性只被瀏覽器用來判斷Cookie是否過期。

Cookie的修改、刪除

Cookie并不提供修改、刪除操作。如果要修改某個Cookie,只需要新建一個同名的Cookie,添加到response中覆蓋原來的Cookie。

如果要刪除某個Cookie,只需要新建一個同名的Cookie,并將maxAge設(shè)置為0,并添加到response中覆蓋原來的Cookie。注意是0而不是負(fù)數(shù)。負(fù)數(shù)代表其他的意義。讀者可以通過上例的程序進(jìn)行驗(yàn)證,設(shè)置不同的屬性。

注意:修改、刪除Cookie時,新建的Cookie除value、maxAge之外的所有屬性,例如name、path、domain等,都要與原Cookie完全一樣。否則,瀏覽器將視為兩個不同的Cookie不予覆蓋,導(dǎo)致修改、刪除失敗。

Cookie的域名

Cookie是不可跨域名的。域名www.google.com頒發(fā)的Cookie不會被提交到域名www.baidu.com去。這是由Cookie的隱私安全機(jī)制決定的。隱私安全機(jī)制能夠禁止網(wǎng)站非法獲取其他網(wǎng)站的Cookie。

正常情況下,同一個一級域名下的兩個二級域名如www.helloweenvsfei.com和 images.helloweenvsfei.com也不能交互使用Cookie,因?yàn)槎叩挠蛎⒉粐?yán)格相同。如果想所有 helloweenvsfei.com名下的二級域名都可以使用該Cookie,需要設(shè)置Cookie的domain參數(shù),例如:

Cookie cookie = new Cookie("time","20080808"); // 新建Cookie

cookie.setDomain(".helloweenvsfei.com"); // 設(shè)置域名

cookie.setPath("/"); // 設(shè)置路徑

cookie.setMaxAge(Integer.MAX_VALUE); // 設(shè)置有效期

response.addCookie(cookie); // 輸出到客戶端

讀者可以修改本機(jī)C:WINDOWSsystem32driversetc下的hosts文件來配置多個臨時域名,然后使用setCookie.jsp程序來設(shè)置跨域名Cookie驗(yàn)證domain屬性。

注意:domain參數(shù)必須以點(diǎn)(".")開始。另外,name相同但domain不同的兩個Cookie是兩個不同的Cookie。如果想要兩個域名完全不同的網(wǎng)站共有Cookie,可以生成兩個Cookie,domain屬性分別為兩個域名,輸出到客戶端。

Cookie的路徑

domain屬性決定運(yùn)行訪問Cookie的域名,而path屬性決定允許訪問Cookie的路徑(ContextPath)。例如,如果只允許/sessionWeb/下的程序使用Cookie,可以這么寫:

Cookie cookie = new Cookie("time","20080808"); // 新建Cookie

cookie.setPath("/session/"); // 設(shè)置路徑

response.addCookie(cookie); // 輸出到客戶端

設(shè)置為“/”時允許所有路徑使用Cookie。path屬性需要使用符號“/”結(jié)尾。name相同但domain相同的兩個Cookie也是兩個不同的Cookie。

注意:頁面只能獲取它屬于的Path的Cookie。例如/session/test/a.jsp不能獲取到路徑為/session/abc/的Cookie。使用時一定要注意。

cookie的不可跨域性

很多網(wǎng)站都會使用Cookie。例如,Google會向客戶端頒發(fā)Cookie,Baidu也會向客戶端頒發(fā)Cookie。那瀏覽器訪問Google會不會也攜帶上Baidu頒發(fā)的Cookie呢?或者Google能不能修改Baidu頒發(fā)的Cookie呢?

答案是否定的。Cookie具有不可跨域名性。根據(jù)Cookie規(guī)范,瀏覽器訪問Google只會攜帶Google的Cookie,而不會攜帶Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。

Cookie在客戶端是由瀏覽器來管理的。瀏覽器能夠保證Google只會操作Google的Cookie而不會操作 Baidu的Cookie,從而保證用戶的隱私安全。瀏覽器判斷一個網(wǎng)站是否能操作另一個網(wǎng)站Cookie的依據(jù)是域名。Google與Baidu的域名 不一樣,因此Google不能操作Baidu的Cookie。

需要注意的是,雖然網(wǎng)站images.google.com與網(wǎng)站www.google.com同屬于Google,但是域名不一樣,二者同樣不能互相操作彼此的Cookie。

Unicode編碼:保存中文

中文與英文字符不同,中文屬于Unicode字符,在內(nèi)存中占4個字符,而英文屬于ASCII字符,內(nèi)存中只占2個字節(jié)。Cookie中使用Unicode字符時需要對Unicode字符進(jìn)行編碼,否則會亂碼。

提示:Cookie中保存中文只能編碼。一般使用UTF-8編碼即可。不推薦使用GBK等中文編碼,因?yàn)闉g覽器不一定支持,而且JavaScript也不支持GBK編碼。

BASE64編碼:保存二進(jìn)制圖片

Cookie不僅可以使用ASCII字符與Unicode字符,還可以使用二進(jìn)制數(shù)據(jù)。例如在Cookie中使用數(shù)字證書,提供安全度。使用二進(jìn)制數(shù)據(jù)時也需要進(jìn)行編碼。

%注意:本程序僅用于展示Cookie中可以存儲二進(jìn)制內(nèi)容,并不實(shí)用。由于瀏覽器每次請求服務(wù)器都會攜帶Cookie,因此Cookie內(nèi)容不宜過多,否則影響速度。Cookie的內(nèi)容應(yīng)該少而精。

Cookie的安全屬性

HTTP協(xié)議不僅是無狀態(tài)的,而且是不安全的。使用HTTP協(xié)議的數(shù)據(jù)不經(jīng)過任何加密就直接在網(wǎng)絡(luò)上傳播,有被截獲的可 能。使用HTTP協(xié)議傳輸很機(jī)密的內(nèi)容是一種隱患。如果不希望Cookie在HTTP等非安全協(xié)議中傳輸,可以設(shè)置Cookie的secure屬性為 true。瀏覽器只會在HTTPS和SSL等安全協(xié)議中傳輸此類Cookie。下面的代碼設(shè)置secure屬性為true:

Cookie cookie = new Cookie("time", "20080808"); // 新建Cookie

cookie.setSecure(true); // 設(shè)置安全屬性

response.addCookie(cookie); // 輸出到客戶端

提示:secure屬性并不能對Cookie內(nèi)容加密,因而不能保證絕對的安全性。如果需要高安全性,需要在程序中對Cookie內(nèi)容加密、解密,以防泄密。

JavaScript操作Cookie

Cookie是保存在瀏覽器端的,因此瀏覽器具有操作Cookie的先決條件。瀏覽器可以使用腳本程序如 JavaScript或者VBScript等操作Cookie。這里以JavaScript為例介紹常用的Cookie操作。例如下面的代碼會輸出本頁面 所有的Cookie。

由于JavaScript能夠任意地讀寫Cookie,有些好事者便想使用JavaScript程序去窺探用戶在其他網(wǎng) 站的Cookie。不過這是徒勞的,W3C組織早就意識到JavaScript對Cookie的讀寫所帶來的安全隱患并加以防備了,W3C標(biāo)準(zhǔn)的瀏覽器會 阻止JavaScript讀寫任何不屬于自己網(wǎng)站的Cookie。換句話說,A網(wǎng)站的JavaScript程序讀寫B(tài)網(wǎng)站的Cookie不會有任何結(jié)果。

案例:永久登錄

如果用戶是在自己家的電腦上上網(wǎng),登錄時就可以記住他的登錄信息,下次訪問時不需要再次登錄,直接訪問即可。實(shí)現(xiàn)方法是把登錄信息如賬號、密碼等保存在Cookie中,并控制Cookie的有效期,下次訪問時再驗(yàn)證Cookie中的登錄信息即可。

保存登錄信息有多種方案。最直接的是把用戶名與密碼都保持到Cookie中,下次訪問時檢查Cookie中的用戶名與密碼,與數(shù)據(jù)庫比較。這是一種比較危險的選擇,一般不把密碼等重要信息保存到Cookie中。

還有一種方案是把密碼加密后保存到Cookie中,下次訪問時解密并與數(shù)據(jù)庫比較。這種方案略微安全一些。如果不希望保存密碼,還可以把登錄的時間戳保存到Cookie與數(shù)據(jù)庫中,到時只驗(yàn)證用戶名與登錄時間戳就可以了。

這幾種方案驗(yàn)證賬號時都要查詢數(shù)據(jù)庫。

本例將采用另一種方案,只在登錄時查詢一次數(shù)據(jù)庫,以后訪問驗(yàn)證登錄信息時不再查詢數(shù)據(jù)庫。實(shí)現(xiàn)方式是把賬號按照一定的規(guī)則加密后,連同賬號一塊保存到Cookie中。下次訪問時只需要判斷賬號的加密規(guī)則是否正確即可。本例把賬號保存到名為account的Cookie中,把賬號連同密鑰用MD1算法加密后保存到名為ssid的Cookie中。驗(yàn)證時驗(yàn)證Cookie中的賬號與密鑰加密后是否與Cookie中的ssid相等。相關(guān)代碼如下:

代碼1.8 loginCookie.jsp

  1. <%@ page language="java"pageEncoding="UTF-8" isErrorPage="false" %> 
  2. <%! // JSP方法 
  3. private static final String KEY =":cookie@helloweenvsfei.com"
  4. // 密鑰 
  5. public final static String calcMD1(Stringss) { // MD1 加密算法 
  6. String s = ss==null ?"" : ss; // 若為null返回空 
  7. char hexDigits[] = { '0','1''2''3''4''1''6''7''8''9'
  8. 'a''b''c''d''e''f' }; // 字典 
  9. try { 
  10. byte[] strTemp =s.getBytes(); // 獲取字節(jié) 
  11. MessageDigestmdTemp = MessageDigest.getInstance("MD1"); // 獲取MD1 
  12. mdTemp.update(strTemp); // 更新數(shù)據(jù) 
  13. byte[] md =mdTemp.digest(); // 加密 
  14. int j =md.length; // 加密后的長度 
  15. char str[] = newchar[j * 2]; // 新字符串?dāng)?shù)組 
  16. int k =0; // 計(jì)數(shù)器k 
  17. for (int i = 0; i< j; i++) { // 循環(huán)輸出 
  18. byte byte0 =md[i]; 
  19. str[k++] =hexDigits[byte0 >>> 4 & 0xf]; 
  20. str[k++] =hexDigits[byte0 & 0xf]; 
  21. return newString(str); // 加密后字符串 
  22. } catch (Exception e){return null; } 
  23. %> 
  24. <% 
  25. request.setCharacterEncoding("UTF-8"); // 設(shè)置request編碼 
  26. response.setCharacterEncoding("UTF-8"); // 設(shè)置response編碼  
  27. String action =request.getParameter("action"); // 獲取action參數(shù)  
  28. if("login".equals(action)){ // 如果為login動作 
  29. String account =request.getParameter("account"); 
  30. // 獲取account參數(shù) 
  31. String password =request.getParameter("password"); 
  32. // 獲取password參數(shù) 
  33. int timeout = newInteger(request.getParameter("timeout")); 
  34. // 獲取timeout參數(shù) 
  35.  
  36. String ssid =calcMD1(account + KEY); // 把賬號、密鑰使用MD1加密后保存
  37.  
  38. CookieaccountCookie = new Cookie("account", account); 
  39. // 新建Cookie 
  40. accountCookie.setMaxAge(timeout); // 設(shè)置有效期 
  41.  
  42. Cookie ssidCookie =new Cookie("ssid", ssid); // 新建Cookie 
  43. ssidCookie.setMaxAge(timeout); // 設(shè)置有效期  
  44.  
  45. response.addCookie(accountCookie); // 輸出到客戶端 
  46. response.addCookie(ssidCookie); // 輸出到客戶端  
  47.  
  48. // 重新請求本頁面,參數(shù)中帶有時間戳,禁止瀏覽器緩存頁面內(nèi)容 
  49. response.sendRedirect(request.getRequestURI() + "?" + System. 
  50. currentTimeMillis()); 
  51. return
  52. elseif("logout".equals(action)){ // 如果為logout動作 
  53.  
  54. CookieaccountCookie = new Cookie("account"""); 
  55. // 新建Cookie,內(nèi)容為空 
  56. accountCookie.setMaxAge(0); // 設(shè)置有效期為0,刪除  
  57. Cookie ssidCookie =new Cookie("ssid"""); // 新建Cookie,內(nèi)容為空 
  58. ssidCookie.setMaxAge(0); // 設(shè)置有效期為0,刪除 
  59. response.addCookie(accountCookie); // 輸出到客戶端 
  60. response.addCookie(ssidCookie); // 輸出到客戶端 
  61. //重新請求本頁面,參數(shù)中帶有時間戳,禁止瀏覽器緩存頁面內(nèi)容 
  62. response.sendRedirect(request.getRequestURI() + "?" + System. 
  63. currentTimeMillis()); 
  64. return
  65. boolean login = false; // 是否登錄 
  66. String account = null; // 賬號 
  67. String ssid = null; // SSID標(biāo)識 
  68.  
  69. if(request.getCookies() !=null){ // 如果Cookie不為空 
  70. for(Cookie cookie :request.getCookies()){ // 遍歷Cookie 
  71. if(cookie.getName().equals("account")) // 如果Cookie名為 
  72. account 
  73. account = cookie.getValue(); // 保存account內(nèi)容 
  74. if(cookie.getName().equals("ssid")) // 如果為SSID 
  75. ssid = cookie.getValue(); // 保存SSID內(nèi)容 
  76. if(account != null && ssid !=null){ // 如果account、SSID都不為空 
  77. login =ssid.equals(calcMD1(account + KEY)); 
  78. // 如果加密規(guī)則正確, 則視為已經(jīng)登錄 
  79. %> 
  80. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN"
  81. <legend><%= login ? "歡迎您回來" : "請先登錄"%></legend> 
  82. <% if(login){%> 
  83. 歡迎您, ${ cookie.account.value }. &nbsp;&nbsp; 
  84.            <a href="${ pageContext.request.requestURI }?action=logout"
  85.             注銷</a> 
  86. <% } else {%> 
  87. <formaction="${ pageContext.request.requestURI }?action=login" 
  88. method="post"
  89.            <table
  90. <tr><td>賬號:</td> 
  91. <td><input type="text"name="account" style="width: 
  92. 200px; "></td> 
  93. </tr> 
  94. <tr><td>密碼:</td> 
  95. <td><inputtype="password" name="password"></td> 
  96. </tr> 
  97. <tr> 
  98. <td>有效期:</td> 
  99. <td><inputtype="radio" name="timeout" value="-1" 
  100. checked> 關(guān)閉瀏覽器即失效 <br/> <input type="radio" 
  101. name="timeout" value="<%= 30 *24 * 60 * 60 %>"> 30天 
  102. 內(nèi)有效 <br/><input type="radio" name="timeout" value= 
  103. "<%= Integer.MAX_VALUE %>"> 永久有效 <br/> </td> </tr> 
  104. <tr><td></td> 
  105. <td><input type="submit"value=" 登 錄 " class= 
  106. "button"></td> 
  107. </tr> 
  108. </table
  109. </form> 
  110. <% } %> 

登錄時可以選擇登錄信息的有效期:關(guān)閉瀏覽器即失效、30天內(nèi)有效與永久有效。通過設(shè)置Cookie的age屬性來實(shí)現(xiàn),注意觀察代碼

提示:該加密機(jī)制中最重要的部分為算法與密鑰。由于MD1算法的不可逆性,即使用戶知道了賬號與加密后的字符串,也不可能解密得到密鑰。因此,只要保管好密鑰與算法,該機(jī)制就是安全的。

 

責(zé)任編輯:武曉燕 來源: 泰斗賢若如
相關(guān)推薦

2025-01-03 09:39:04

2023-10-24 09:07:14

CookieSessionHTTP

2023-10-27 08:23:10

CookieWeb存儲

2025-04-09 05:00:00

CookieSession服務(wù)器

2014-08-18 09:31:15

2023-10-04 00:05:00

SessionCookie

2009-08-05 18:30:36

Session和CooASP.NET表單

2019-11-06 17:30:57

cookiesessionWeb

2024-10-09 15:43:49

2022-11-16 07:43:49

RabbitMQAMQP協(xié)議

2020-11-05 09:26:55

Cookie和Sess

2019-05-15 15:10:12

Tomcat Session Cookie

2019-06-11 14:45:25

2019-11-07 10:37:36

CookieSessionToken

2010-08-04 10:03:57

jQuery

2023-12-04 10:36:46

SessionCookie

2021-08-26 06:58:14

CookieSession應(yīng)用

2023-12-11 11:29:35

2019-12-04 13:50:07

CookieSessionToken

2021-08-09 08:53:30

HTTP狀態(tài)化協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號