[04] Cookie概念和基本使用
阿新 • • 發佈:2017-09-01
googl fsg 發現 mage oaf 文件格式 veh ddc 無法讀取
很多網站在你瀏覽後,會在你電腦中留下小小的檔案,也就是我們說的Cookie,以便你再次瀏覽時,網站會讀取它上次給你留下的Cookie資料,如果有的話,就可以根據內容來判斷使用者,送出特定的網頁內容。
因為HTTP協議是無狀態的,即服務器不知道用戶上一次做了什麽,這嚴重阻礙了交互式Web應用程序的實現。所以Cookie就是用來繞開HTTP的無狀態性的“額外手段”之一。
Cookie的一個典型的應用是當登錄一個網站時,網站往往會請求用戶輸入用戶名和密碼,並且用戶可以勾選“下次自動登錄”。如果勾選了,那麽下次訪問同一網站時,用戶會發現沒輸入用戶名和密碼就已經登錄了。這正是因為前一次登錄時,服務器發送了包含登錄憑據(用戶名加密碼的某種加密形式)的Cookie到用戶的硬盤上。第二次登錄時,(如果該Cookie尚未到期)瀏覽器會發送該Cookie,服務器驗證憑據,於是不必輸入用戶名和密碼就讓用戶登錄了。
所以:
但是要註意的是,Cookie既然能把小文本保存在客戶端,並在服務器和客戶端之間進行傳輸,那麽意味著它也容易造成信息泄露,因此:
另外,Cookie還有一些缺陷 :
如果你想看到自己的Cookie,也打開某個網站,在控制臺調用JS代碼: javascript:alert("Cookie:"+document.cookie) 或 javascript:document.write(document.cookie)
可以看到,Cookie對象是保存一對鍵值對,都是字符串形式。
Cookie類定義了一系列的方法,摘要部分如下:
保存和獲取Cookie:
Cookie要保存到客戶端,凡是寫到客戶端的方法,基本都是在響應中,HttpServletResponse提供了方法,把Cookie保存到客戶端;而再次訪問與保存Cookie相同域名的網站時,HTTP協議將把有效時間內的Cookie都發送到服務器,容器將Cookie封裝到請求中,HttpServletRequest提供了獲取Cookie對象數組的方法。
寫登陸頁面展示如下:![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134552827-1755619363.png)
寫後臺Servlet代碼如下:
該示例中,輸入賬戶密碼登陸後,Servlet中最後會調用response.addCookie方法,將賬號密碼存到客戶端的硬盤上。
我們就到硬盤裏去翻一翻,在這之前要說明的是:
可以看到,除了剛才登陸的localhost,也還有平時登陸其他網站留下的Cookie,我們看剛才登陸的localhost的Cookie就行了:![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134559577-432580408.png)
可見,確實把我們的賬號和密碼放到了Cookie中,並發送到了客戶端的硬盤裏:
但索性我們還是可以直接在瀏覽器中看到的:
Cookie的內容當然不止我們定義的那對key/value,實際上它是有一定格式的。Cookie的標準格式定義在不同瀏覽器中實現,在歷史上也有差異。下面是常用的標準格式,或者說屬性:
這裏再說明一下path和domain,假設寫Cookie的程序的訪問路徑是 http://localhost:8080/JavaWeb/servlet/CookieDemo
假設現瀏覽器存的cookie的路徑是/JavaWeb/servlet/,則:
也就是說,Cookie有個不可跨域名性,就像訪問Google只會帶上Google的Cookie,而不會帶上Baidu的Cookie。
如下示例圖,訪問淘寶網時攜帶的Cookie:
但是這裏不做展開,留下部分參考,以便未來學習:
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關鍵字進行創建:
Cookie cookie
= new Cookie("username", "zhangsan");
可以看到,Cookie對象是保存一對鍵值對,都是字符串形式。
Cookie類定義了一系列的方法,摘要部分如下:
類型 | 方法名 | 說明 |
void | setMaxAge(int expiry) | 設置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
上面單純文字的說明太過幹癟,那麽就來一個生動鮮活的例子:寫登陸頁面展示如下:
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134552827-1755619363.png)
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>登陸頁面</title>
</head>
<body>
<%
String username = null;
String password = null;
//獲取請求中的所有cookie對象
Cookie[] cookies = request.getCookies();
//只要存在Cookie,就查找是否有用戶名和密碼
if(cookies != null) {
for(Cookie cookiesTemp : cookies) {
if(cookiesTemp.getName().equals("username")) {
username = cookiesTemp.getValue();
}
if(cookiesTemp.getName().equals("password")) {
password = cookiesTemp.getValue();
}
}
}
if(username != null && password != null) {
request.getRequestDispatcher("LoginServlet?username=" + username + "&pwd=" + password).forward(request, response);
}
%>
<form name="form1" action="LoginServlet" method="post">
用戶名:<input type="text" id="username" name="username"><br>
密碼:<input type="password" id="pwd" name="pwd"><br>
<select id="timelength" name="timelength">
<option value="0" selected>每次都需要登陸</option>
<option value="3">3天內免登陸</option>
<option value="7">7天內免登陸</option>
</select><br>
<input type="submit" name="submit" value="登陸">
</form>
</body>
</html>
寫後臺Servlet代碼如下:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset = utf-8");
//獲取用戶名、密碼
String username = request.getParameter("username");
String password = request.getParameter("pwd");
//獲得JSP頁面的時間信息
String timelength = request.getParameter("timelength");
int days = 0;
//類型轉換
if(timelength != null) {
days = Integer.parseInt(timelength);
}
//只要天數不為0,則創建cookie,設置有效時間,存到客戶端
if(days != 0) {
Cookie usernameCookie = new Cookie("username", username);
Cookie passwordCookie = new Cookie("password", password);
usernameCookie.setMaxAge(days * 24 * 3600);
passwordCookie.setMaxAge(days * 24 * 3600);
response.addCookie(usernameCookie);
response.addCookie(passwordCookie);
}
//跳轉到home.jsp
request.getRequestDispatcher("home.jsp").forward(request, response);
}
該示例中,輸入賬戶密碼登陸後,Servlet中最後會調用response.addCookie方法,將賬號密碼存到客戶端的硬盤上。
我們就到硬盤裏去翻一翻,在這之前要說明的是:
- 不同瀏覽器的Cookie存放位置不同
- 不同瀏覽器的Cookie存放文件格式不同,IE采用明文的文本文件,Safari采用二進制文件,Chrome和Firefox采用的是Sqlite數據庫文件格式
3.1 IE
為了方便展示,我們用IE瀏覽器登陸一次,然後可以在瀏覽器設置中,找到存放Cookie文件的位置:![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134556812-2010350000.png)
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134559577-432580408.png)
可見,確實把我們的賬號和密碼放到了Cookie中,並發送到了客戶端的硬盤裏:
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134607093-804422310.png)
3.2 Chrome
Chrome因為文件格式問題,直接在硬盤上打開實際上你看到的基本都是亂碼:![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134608249-1819906798.jpg)
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134611812-924740155.png)
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134614155-1702181822.jpg)
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134616171-2109357399.png)
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:
![技術分享](http://images2017.cnblogs.com/blog/1007017/201709/1007017-20170901134618171-1292475108.png)
5、最後
因為Cookie實現自動登錄涉及到用戶信息安全的問題,實際上真正的自動登錄不會像上面這麽簡單粗暴的,從我們查看Cookie就可以知道,賬號密碼都可以赤裸裸地看到,這顯然是不行的。但是這裏不做展開,留下部分參考,以便未來學習:
- 理解Cookie和Session機制
- 記住密碼功能如何設計?
- 網站的下次自動登錄功能的實現方法
- cookie實現自動登錄
[04] Cookie概念和基本使用