1. 程式人生 > >[04] Cookie概念和基本使用

[04] Cookie概念和基本使用

googl fsg 發現 mage oaf 文件格式 veh ddc 無法讀取


1、Cookie是什麽

Cookie,中文名稱為“小型文本文件”或“小甜餅”,指某些網站為了辨別用戶身份而儲存在用戶本地終端上的數據(通常經過加密)。

很多網站在你瀏覽後,會在你電腦中留下小小的檔案,也就是我們說的Cookie,以便你再次瀏覽時,網站會讀取它上次給你留下的Cookie資料,如果有的話,就可以根據內容來判斷使用者,送出特定的網頁內容。
因為HTTP協議是無狀態的,即服務器不知道用戶上一次做了什麽,這嚴重阻礙了交互式Web應用程序的實現。所以Cookie就是用來繞開HTTP的無狀態性的“額外手段”之一。

Cookie的一個典型的應用是當登錄一個網站時,網站往往會請求用戶輸入用戶名和密碼,並且用戶可以勾選“下次自動登錄”。如果勾選了,那麽下次訪問同一網站時,用戶會發現沒輸入用戶名和密碼就已經登錄了。這正是因為前一次登錄時,服務器發送了包含登錄憑據(用戶名加密碼的某種加密形式)的Cookie到用戶的硬盤上。第二次登錄時,(如果該Cookie尚未到期)瀏覽器會發送該Cookie,服務器驗證憑據,於是不必輸入用戶名和密碼就讓用戶登錄了。

技術分享


所以:
  • Cookie是保存在客戶端的小文本
  • 保存位置分兩種
    • (1)保存在客戶端瀏覽器所占內存中,關閉瀏覽器後Cookie也消失
    • (2)保存在客戶端PC機的硬盤上,設置有效時間,超期後失效

但是要註意的是,Cookie既然能把小文本保存在客戶端,並在服務器和客戶端之間進行傳輸,那麽意味著它也容易造成信息泄露,因此:
  • 不用Cookie保存對保密性要求高的信息,如銀行卡密碼等
  • 不用Cookie實現某些必要功能,防止Cookie刪除後功能出現錯誤
  • 可以通過瀏覽器設置阻止Cookie,或手工清除Cookie
  • Cookie放在請求頭Header裏,而不是主體Body中,所以GET或POST方式的請求都可以發送Cookie

另外,Cookie還有一些缺陷
  • Cookie會被附加在每個HTTP請求中,所以無形中增加了流量
  • 由於在HTTP請求中的Cookie是明文傳遞的,所以安全性成問題(除非用HTTPS)
  • Cookie的大小限制在4KB左右。對於復雜的存儲需求來說是不夠用的

如果你想看到自己的Cookie,也打開某個網站,在控制臺調用JS代碼: javascript:alert("Cookie:"+document.cookie) 或 javascript:document.write(document.cookie)

2、Java中的Cookie類

在Servlet API中,存在Cookie類,可以使用new關鍵字進行創建:
  1. Cookie cookie
    = new Cookie("username", "zhangsan");

可以看到,Cookie對象是保存一對鍵值對,都是字符串形式
Cookie類定義了一系列的方法,摘要部分如下:
類型 方法名 說明
void setMaxAge(int expiry) 設置Cookie有效期,以秒為單位,保存在硬盤上或內存中
  • 正數:保存到客戶端硬盤上,一定時間有效
  • 負數:瀏覽器關閉時Cookie被刪除
  • 零:Cookie被刪除
void setValue(String value) Cookie創建後,對Cookie進行賦值
String getName() 獲取Cookie的名稱
String getValue() 獲取Cookie的值
String getMaxAge() 獲取Cookie的有效時間,以秒為單位

保存和獲取Cookie
  • 把Cookie保存到客戶端 response.addCookie(Cookie cookie)
  • 獲取請求中的Cookies request.getCookies()

Cookie要保存到客戶端,凡是寫到客戶端的方法,基本都是在響應中,HttpServletResponse提供了方法,把Cookie保存到客戶端;而再次訪問與保存Cookie相同域名的網站時,HTTP協議將把有效時間內的Cookie都發送到服務器,容器將Cookie封裝到請求中,HttpServletRequest提供了獲取Cookie對象數組的方法。

3、一個示例帶你看Cookie

上面單純文字的說明太過幹癟,那麽就來一個生動鮮活的例子:
寫登陸頁面展示如下:技術分享
  1. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  6. <title>登陸頁面</title>
  7. </head>
  8. <body>
  9. <%
  10. String username = null;
  11. String password = null;
  12. //獲取請求中的所有cookie對象
  13. Cookie[] cookies = request.getCookies();
  14. //只要存在Cookie,就查找是否有用戶名和密碼
  15. if(cookies != null) {
  16. for(Cookie cookiesTemp : cookies) {
  17. if(cookiesTemp.getName().equals("username")) {
  18. username = cookiesTemp.getValue();
  19. }
  20. if(cookiesTemp.getName().equals("password")) {
  21. password = cookiesTemp.getValue();
  22. }
  23. }
  24. }
  25. if(username != null && password != null) {
  26. request.getRequestDispatcher("LoginServlet?username=" + username + "&pwd=" + password).forward(request, response);
  27. }
  28. %>
  29. <form name="form1" action="LoginServlet" method="post">
  30. 用戶名:<input type="text" id="username" name="username"><br>
  31. 密碼:<input type="password" id="pwd" name="pwd"><br>
  32. <select id="timelength" name="timelength">
  33. <option value="0" selected>每次都需要登陸</option>
  34. <option value="3">3天內免登陸</option>
  35. <option value="7">7天內免登陸</option>
  36. </select><br>
  37. <input type="submit" name="submit" value="登陸">
  38. </form>
  39. </body>
  40. </html>

寫後臺Servlet代碼如下:
  1. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. response.setContentType("text/html; charset = utf-8");
  3. //獲取用戶名、密碼
  4. String username = request.getParameter("username");
  5. String password = request.getParameter("pwd");
  6. //獲得JSP頁面的時間信息
  7. String timelength = request.getParameter("timelength");
  8. int days = 0;
  9. //類型轉換
  10. if(timelength != null) {
  11. days = Integer.parseInt(timelength);
  12. }
  13. //只要天數不為0,則創建cookie,設置有效時間,存到客戶端
  14. if(days != 0) {
  15. Cookie usernameCookie = new Cookie("username", username);
  16. Cookie passwordCookie = new Cookie("password", password);
  17. usernameCookie.setMaxAge(days * 24 * 3600);
  18. passwordCookie.setMaxAge(days * 24 * 3600);
  19. response.addCookie(usernameCookie);
  20. response.addCookie(passwordCookie);
  21. }
  22. //跳轉到home.jsp
  23. request.getRequestDispatcher("home.jsp").forward(request, response);
  24. }

該示例中,輸入賬戶密碼登陸後,Servlet中最後會調用response.addCookie方法,將賬號密碼存到客戶端的硬盤上。
我們就到硬盤裏去翻一翻,在這之前要說明的是:
  • 不同瀏覽器的Cookie存放位置不同
  • 不同瀏覽器的Cookie存放文件格式不同,IE采用明文的文本文件,Safari采用二進制文件,Chrome和Firefox采用的是Sqlite數據庫文件格式

3.1 IE

為了方便展示,我們用IE瀏覽器登陸一次,然後可以在瀏覽器設置中,找到存放Cookie文件的位置:技術分享 可以看到,除了剛才登陸的localhost,也還有平時登陸其他網站留下的Cookie,我們看剛才登陸的localhost的Cookie就行了:技術分享
可見,確實把我們的賬號和密碼放到了Cookie中,並發送到了客戶端的硬盤裏:技術分享

3.2 Chrome

Chrome因為文件格式問題,直接在硬盤上打開實際上你看到的基本都是亂碼:技術分享 技術分享 但索性我們還是可以直接在瀏覽器中看到的: 技術分享 技術分享

4、Cookie的格式

我們已經知道了Cookie是個小文本,而且也基本是按照key/value的方式存儲,所以也才有了封裝的Cookie對象用來保存一對鍵值對。
Cookie的內容當然不止我們定義的那對key/value,實際上它是有一定格式的。Cookie的標準格式定義在不同瀏覽器中實現,在歷史上也有差異。下面是常用的標準格式,或者說屬性:
  • name 用戶可定義的key
  • value 用戶可定義的value
  • comment 用來提供註釋說明
  • path 指定Cookie作用路徑,和Domain配合限制Cookie的作用範圍
  • domain 指定作用域
  • max-age 指定Cookie失效時間
  • secure 用來遠程發送Cookie時告知瀏覽器數據已加密,只能HTTPS連接被發送
  • httponly 本地JavaScript無法讀取Cookie信息

這裏再說明一下path和domain,假設寫Cookie的程序的訪問路徑是 http://localhost:8080/JavaWeb/servlet/CookieDemo
  • localhost就是域名
  • /JavaWeb/servlet就是當前Cookie的path

假設現瀏覽器存的cookie的路徑是/JavaWeb/servlet/,則:
  • 訪問的地址是:http://localhost:8080/JavaWeb/servlet/CookieDemo 則帶該cookie
  • 訪問的地址是:http://localhost:8080/JavaWeb/CookieDemo 則不帶該cookie

也就是說,Cookie有個不可跨域名性,就像訪問Google只會帶上Google的Cookie,而不會帶上Baidu的Cookie。
如下示例圖,訪問淘寶網時攜帶的Cookie:技術分享

5、最後

因為Cookie實現自動登錄涉及到用戶信息安全的問題,實際上真正的自動登錄不會像上面這麽簡單粗暴的,從我們查看Cookie就可以知道,賬號密碼都可以赤裸裸地看到,這顯然是不行的。
但是這裏不做展開,留下部分參考,以便未來學習:
  • 理解Cookie和Session機制
  • 記住密碼功能如何設計?
  • 網站的下次自動登錄功能的實現方法
  • cookie實現自動登錄


[04] Cookie概念和基本使用