Cookie

Cookie

在程序中,會話跟蹤是很重要的事情。理論上,一個用戶的所有請求操作都應該屬于同一個會話,而另一個用戶的所有請求操作則應該屬于另一個會話,二者不能混淆。例如,用戶A在超市購買的任何商品都應該放在A的購物車內,不論是用戶A什么時間購買的,這都是屬于同一個會話的,不能放入用戶B或用戶C的購物車內,這不屬于同一個會話。

而Web應用程序是使用HTTP協(xié)議傳輸數據的。HTTP協(xié)議是無狀態(tài)的協(xié)議。一旦數據交換完畢,客戶端與服務器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味著服務器無法從連接上跟蹤會話。即用戶A購買了一件商品放入購物車內,當再次購買商品時服務器已經無法判斷該購買行為是屬于用戶A的會話還是用戶B的會話了。要跟蹤該會話,必須引入一種機制。

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

在 Servlet 規(guī)范中,常用以下兩種機制完成會話跟蹤

Cookie
Session

Cookie機制

cookie機制采用的是在客戶端保持 HTTP 狀態(tài)信息的方案。

Cookie意為“甜餅”,是由W3C組織提出,最早由Netscape社區(qū)發(fā)展的一種機制。目前Cookie已經成為標準,所有的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。

由于HTTP是一種無狀態(tài)的協(xié)議,服務器單從網絡連接上無從知道客戶身份。怎么辦呢?就給客戶端們頒發(fā)一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工作原理。

Cookie實際上是一小段的文本信息??蛻舳苏埱蠓掌?,如果服務器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個Cookie??蛻舳藶g覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態(tài)。

一個Cookie只能標識一種信息,它至少含有一個標識該信息的名稱(NAME)和設置值(VALUE)。

Cookie的傳送過程示意圖

image.png

一個Cookie只能記住一個信息。

@WebServlet("/cookie")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 在JavaWEB規(guī)范中使用Cookie類代表cookie
        // 1.創(chuàng)建一個Cookie對象
        Cookie cookie = new Cookie("name","neusoft");
        // 2.調用response的一個方法把Cookie傳給客戶端
        response.addCookie(cookie);
    }
}

Servlet API中提供了一個javax.servlet.http.Cookie類來封裝Cookie信息,它包含有生成Cookie信息和提取Cookie信息的各個屬性的方法。

Cookie類的方法:
--構造方法: public Cookie(String name,String value)
--getName方法
--setValue與getValue方法
--setMaxAge與getMaxAge方法
--setPath與getPath方法

HttpServletResponse接口中定義了一個addCookie方法,它用于在發(fā)送給瀏覽器的HTTP響應消息中增加一個Set-Cookie響應頭字段。
HttpServletRequest接口中定義了一個getCookies方法,它用于從HTTP請求消息的Cookie請求頭字段中讀取所有的Cookie項。

@WebServlet("/GetCookieServlet")
public class GetCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        // 1.獲取 Cookie(沒有單獨獲取某一個Cookie的方法)
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length >= 1){
            boolean bFind = false;
            for(Cookie cookie:cookies){
                if(cookie.getName().equals("name"))
                {
                    bFind = true;
                }
            }
            if(bFind)
            {
                out.print("neusoft Cookie exist");
            }
            else {
                out.print("no Cookie,create one and return");
                // 1.創(chuàng)建一個Cookie對象
                Cookie cookie = new Cookie("name","neusoft");

                // 2.調用response的一個方法Cookie傳給客戶端
                response.addCookie(cookie);
            }
        }else{
            out.print("no Cookie,create one and return");
            // 1.創(chuàng)建一個Cookie對象
            Cookie cookie = new Cookie("name","neusoft");

            // 2.調用response的一個方法Cookie傳給客戶端
            response.addCookie(cookie);
        }
    }
}

如果創(chuàng)建了一個cookie,并將他發(fā)送到瀏覽器,默認情況下它是一個會話級別的cookie; 存儲在瀏覽器的內存中,用戶退出瀏覽器之后被刪除。若希望瀏覽器將該cookie存儲在磁盤上,則需要使用maxAge,并給出一個以秒為單位的時間。將最大時效設為0則是命令瀏覽器刪除該cookie。

發(fā)送cookie需要使用HttpServletResponse的addCookie方法,將cookie插入到一個 Set-Cookie HTTP響應報頭中。由于這個方法并不修改任何之前指定的Set-Cookie報頭,而是創(chuàng)建新的報頭,因此將這個方法稱為是addCookie,而非setCookie。

setMaxAge(秒)設置Cookie的最大時效,若為0代表立即上除該Cookie,若為負數表述不存儲該Cookie

@WebServlet("/GetCookieServlet")
public class GetCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        // 1.獲取 Cookie(沒有單獨獲取某一個Cookie的方法)
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length >= 1){
            boolean bFind = false;
            for(Cookie cookie:cookies){
                if(cookie.getName().equals("name"))
                {
                    bFind = true;
                }
            }
            if(bFind)
            {
                out.print("neusoft Cookie exist");
            }
            else {
                out.print("no Cookie,create one and return");
                // 1.創(chuàng)建一個Cookie對象
                Cookie cookie = new Cookie("name","neusoft");
                cookie.setMaxAge(200);
                // 2.調用response的一個方法Cookie傳給客戶端
                response.addCookie(cookie);
            }
        }else{
            out.print("no Cookie,create one and return");
            // 1.創(chuàng)建一個Cookie對象
            Cookie cookie = new Cookie("name","neusoft");
            cookie.setMaxAge(200);
            // 2.調用response的一個方法Cookie傳給客戶端
            response.addCookie(cookie);
        }
    }
}

課堂案例--1:
利用Cookie進行自動登錄
index.jsp

<%@ 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>Insert title here</title>
</head>
<body>
  <a href="admin.do">進入后臺</a>
</body>
</html>

admin.do

@WebServlet("/admin.do")
public class AdminServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = "";
                // 沒有得到參數,遍歷看是否有
        Cookie cookies[] = request.getCookies();

        if(cookies != null && cookies.length > 0){
            for(Cookie cookie:cookies){
                String cookieName = cookie.getName();
                if(cookieName.equals("username")){
                    username = cookie.getValue();
                }
            }
        }
        if(username != null && !username.trim().equals("")){
            response.getWriter().print("Hello:"+username);
        }else{
            response.sendRedirect("login.jsp");
        }
    }
}

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="login.do" method="post">
    username:<input type="text" name="username">
    <input type="submit" value="確定">
</form>
</body>
</html>

login.do

@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        String username = request.getParameter("username");
        // 獲取到參數,設置最大時效,發(fā)給瀏覽器
        if(username != null && !username.trim().equals("")){
            Cookie cookie = new Cookie("username",username);
            cookie.setMaxAge(300);
            response.addCookie(cookie);
            response.getWriter().print("Hello:"+username);
        }
    }

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

    }
}

Cookie的Path問題

@WebServlet("/path/PathServlet")
public class PathServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("name","neusoft");
        response.addCookie(cookie);
    }
}
@WebServlet("/GetCookieServlet")
public class GetCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        // 1.獲取 Cookie(沒有單獨獲取某一個Cookie的方法)
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length >= 1){
            boolean bFind = false;
            for(Cookie cookie:cookies){
                if(cookie.getName().equals("name"))
                {
                    bFind = true;
                }
            }
            if(bFind)
            {
                out.print("neusoft Cookie exist");
            }
            else {
                out.print("no Cookie,create one and return");
            }
        }else{
            out.print("no Cookie,create one and return");
        }
    }
}

運行是讀取不到的,路徑調換一下,可以讀到
Cookie的作用范圍:可以作用當前目錄和當前目錄的子目錄,但不能作用與當前目錄的上一級目錄
如何解決:

@WebServlet("/path/PathServlet")
public class PathServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("name","neusoft");
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}

${pageContext.request.contextPath}

<a href="${pageContext.request.contextPath}/sport/view.do"></a>

cookie.setPath("/");

Cookie小結

(1)簡介
Cookie機制采用的是在客戶端保持 HTTP 狀態(tài)信息的方案。

Cookie實際上是一小段的文本信息。客戶端請求服務器,如果服務器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個Cookie??蛻舳藶g覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態(tài)。

(2)作用
Cookie的根本作用就是在客戶端存儲用戶訪問網站的一些信息。典型的應用有:

自動登錄。

(3)缺陷
①Cookie會被附加在每個HTTP請求中,所以無形中增加了流量。

②由于在HTTP請求中的Cookie是明文傳遞的,所以安全性成問題。(除非用HTTPS)

③Cookie的大小限制在4KB左右。對于復雜的存儲需求來說是不夠用的。

(4)常用方法
創(chuàng)建Cookie:Cookie cookie = new Cookie(name,value)

向瀏覽器發(fā)送Cookie:response.addCookie(cookie)

設置最大時效:cookie.setMaxAge(秒),當設置為0的時候,使用response.addCookie(cookie),表示刪除該cookie。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容