JavaWeb--Cookie與Session

2022-08-03 06:00:26

前言

  • Java Web 其實就是一個技術的總和,把Web看成一個容器而已主要使用JavaEE技術來實現.在加上各種中介軟體。
  • 整個javaWeb階段的內容通過實際的案例貫穿學習, 所涉及到的技術知識點會在案例中根據不同的需求引入。
  • 首先了解javaWeb的整個技術體系,掌握常用的技術知識點。

我會將JavaWeb分為8篇左右的文章來記錄自己的學習過程,也方便大家逐級遞增難度的學習,如有錯誤或遺漏歡迎大家指出。

注:本篇文章承接上一篇JavaWeb文章JavaWeb--Servlet詳解
下面我們進入正題!

7、Cookie、Session

7.1、對談

對談:使用者開啟了一個瀏覽器,點選了很多超連結,存取多個web資源,關閉瀏覽器,這個過程可以稱之為對談

有狀態對談:記錄了一些資訊

大家在瀏覽網站的過程中有沒有思考過這樣一個問題,一個網站怎麼證明客戶存取過呢?

使用者端 伺服器端

1.伺服器端給使用者端一個信件,使用者端下次存取伺服器端帶上信件就可以了 : cookie

2.伺服器登記客戶已經來過了,下次存取的時候直接匹配登記過的客戶 ; session

3.大家可以先看一下這張圖,下面對Cookie與Session的講解就是圍繞這張圖展開的,最後會對這張圖進行詳細的講解

7.2、儲存對談的兩種技術

7.2.1、cookie

  • 使用者端技術(響應,請求)
  • cookie一般是以鍵值對的形式進行表示的(key-value)
  • 我們登入過一個網站,當我們再次開啟就不需要再次登入了

7.2.2、session

  • 伺服器技術(儲存使用者的對談資訊,可以把資訊或者資料放在session中)
  • 每個使用者端都有自己的一個Session對談
  • Session對談中,我們經常用來儲存使用者登入之後的資訊

大部分的網站:網站登入之後,下次就不用再登入了,第二次存取直接就可以登入進去

7.3、Cookie

1.cookie中常用屬性的解釋

  • Name:這個是cookie的名字
  • Value:這個是cooke的值
  • path:這個定義了Web站點上可以存取該Cookie的目錄
  • Expircs:這個值表示cookie的過期時間,也就是有效值,cookic在這個值之前都有效。
  • size:這個表示cookic的大小

2.Cookie的Http傳輸

Cookie的Http傳輸 我們會在接下來的例子中進行抓包展示

3.Cookie的生命週期

cookie有2種儲存方式,一種是對談性,一種是永續性

  • 對談性:如果cookie為對談性,那麼cookie僅會儲存在使用者端的記憶體中,當我們關閉客服端時cookie也就失效了
  • 永續性:如果cookie為永續性,那麼cookie會儲存在使用者的硬碟中,直至生存期結束或者使用者主動將其銷燬。

cookie我們是可以進行設定的,我們可以人為設定cookie的有效時間,什麼時候建立,什麼時候銷毀。

4.cookie 使用的常見方法

java中Cookie物件的方法進行講解

  • new Cookie(String name, String value):建立一個Cookie物件,必須傳入cookie的名字和cookic的值
  • setValue():得到cookie儲存的值
  • getName():獲取cookie的名字
  • setMaxAge(int expiry):設定cookie的有效期,預設為-1。這個如果設定負數,表示客服端關閉,cookie就會刪除。0表示馬上刪除。正數表示有效時間,單位是秒
  • setPath(String uri):設定cookie的作用域

HttpServletRequest和Http ServletResponse對Cookie進行操作的常見方法

  • response.addCookie(Cookie cookie):將cookie給使用者端進行儲存
  • resquest.getCookies0:得到客服端傳過來的所有cookie物件

這張圖是使用者端攜帶Cookie存取伺服器的流程圖

7.3.1、用程式碼實現儲存使用者上一次存取的時間

  1. 從請求中拿到cookie資訊

  2. 伺服器端響應給使用者端cookie

//儲存使用者上一次存取的時間

public class CookieDemon01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //伺服器告訴你你來的時間,把這個時間封裝為一個信件,你下次來,我就知道你來了


        //解決中文亂碼,這裡解決亂碼需要根據實際情況自己進行偵錯
        req.setCharacterEncoding("gbk");
        resp.setCharacterEncoding("gbk");

        PrintWriter out = resp.getWriter();

        //cookie,伺服器端從使用者端獲取
        Cookie[] cookies = req.getCookies();//返回陣列說明cookie可能存在多個

        //判斷cookie是否存在
        if (cookies != null) {
        //如果存在怎麼辦
            out.write("您上一次存取的時間是:");

            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //獲取cookie的名字

               if( cookie.getName().equals("LastLogTime")){
                   //獲取cookie的值

                   long lastLogTime = Long.parseLong(cookie.getValue());
                   Date date = new Date(lastLogTime);
                   out.write(date.toLocaleString());

               }
            }
            
        }else {
            out.write("這是您第一次存取本站");
        }
        
        //伺服器給使用者端響應一個cookie

        Cookie cookie = new Cookie("LastLogTime", System.currentTimeMillis()+"");
        //設定cookie有效期為一天(瀏覽器關閉cookie還存在一天)
        cookie.setMaxAge(24*60*60);

        resp.addCookie(cookie);

        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3.註冊Servlet

 <servlet>
    <servlet-name>CookieDemo01</servlet-name>
    <servlet-class>com.qid.servlet.CookieDemon01</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>CookieDemo01</servlet-name>
    <url-pattern>/c1</url-pattern>

4.測試存取

第一次存取

第二次存取

接下來我們抓包檢視Cookie的Http傳輸

注:cookie一般會儲存在原生的使用者目錄下AppData ,瀏覽器只會攜帶在當前請求的URL中包含了改cookie中path值的cookie

瞭解一下:
一個網站cookie是否存在上限?

  • 一個cookie只能儲存一個資訊
  • 一個web站點可以給瀏覽器傳送多個cookie,最多存放20個cookie
  • cookie大小上限為4kb
  • 300個cookie大約為瀏覽器上限

7.3.2、刪除cookie:

  • 不設定有效期,關閉瀏覽器,自動失效

  • 設定有效期為0

    public class CookieDemon02 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       
            //建立一個cookie.名字必須和要刪除的名字一致
            Cookie cookie = new Cookie("LastLogTime", System.currentTimeMillis()+"");
            //有限期為0
            cookie.setMaxAge(0);
    
            resp.addCookie(cookie);
            
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

7.3.3、中文傳輸資料亂碼問題

這裡再用上面記錄存取時間的例子說一下傳輸中文資料的問題:

如果一直中文傳輸資料亂碼,可以嘗試以下程式碼:

編碼解碼

//編碼
Cookie cookie = new Cookie("name", URLEncoder.encode("張三","utf-8"));
 //解碼
 out.write( URLDecoder.decode(cookie.getValue(),"utf-8"));

整體程式碼:


//中文資料傳遞

public class CookieDemon03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //解決中文亂碼
        req.setCharacterEncoding("utf-16");
        resp.setCharacterEncoding("utf-16");
        //cookie,伺服器端從使用者端獲取
        Cookie[] cookies = req.getCookies();//返回陣列說明cookie可能存在多個


        PrintWriter out = resp.getWriter();

        //判斷cookie是否存在
        if (cookies != null) {
            //如果存在怎麼辦
            out.write("您的名字是:");

            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //獲取cookie的名字

                if( cookie.getName().equals("name")){
                    //獲取cookie的值
                    System.out.println(cookie.getValue());
                   //解碼
                    out.write( URLDecoder.decode(cookie.getValue(),"utf-8"));

                }
            }

        }else {
            out.write("這是您第一次存取本站");
        }
        //編碼
        Cookie cookie = new Cookie("name", URLEncoder.encode("張三","utf-8"));
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

註冊servlet後測試結果

7.4、Session(重點)

7.4.1、Session的概念

1.什麼是session

  • 伺服器會給每一個使用者(瀏覽器)建立一個Session
  • 一個Session獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就存在
  • 使用者登入之後,整個網站它都可以存取--->儲存使用者的資訊

2.Session的常用方法

  • request.getSession():建立(第一次呼叫)或獲取Session對談物件
  • isNew():判斷當前Session對談是否是新建立出來的
  • getId():得到Session的對談ID
  • setAttribute():往Session中儲存資料
  • getAttribute():獲取Session域中的資料

3.Session的生命週期

  • 手動登出:session.invalidate();

  • 自動登出:在web.xml 中設定

<!--設定session預設失效時間-->
  <session-config>
<!--15分鐘後session自動失效,以分鐘為單位-->
    <session-timeout>15</session-timeout>
  </session-config>

4.session應用:

  • 儲存一個登入使用者的資訊
  • 購物車資訊
  • 在整個網站中經常會使用的資料,我們將它儲存在Session中

下面這張圖是伺服器登記session,使用者端用sessionID存取的流程圖

7.4.2、具體使用session

1.儲存資料:

  • Person.java
  • SessionDemon01(設定資訊)
  • SessionDemon02(得到資訊)
public class Person {

    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class SessionDemon01 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //解決亂碼問題
        req.setCharacterEncoding("gbk");
        resp.setCharacterEncoding("gbk");
        resp.setContentType("text/html;charset = gbk");

        //得到Session

        HttpSession session = req.getSession();

        //給Session中存東西
        session.setAttribute("name",new Person("李四",18));


        //獲取session的id
        String sessionId = session.getId();

        //判斷session是不是新建立的
        if(session.isNew()){
            resp.getWriter().write("session建立成功,id:"+sessionId);
        }else {
            resp.getWriter().write("session已經在伺服器中存在了,id:"+sessionId);
        }


        //Session建立的時候做了什麼事情
//        Cookie cookie = new Cookie("JSESSIONID",sessionId);
//        resp.addCookie(cookie);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class SessionDemon02 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //解決亂碼問題
        req.setCharacterEncoding("gbk");
        resp.setCharacterEncoding("gbk");
        resp.setContentType("text/html;charset = gbk");

        //得到Session

        HttpSession session = req.getSession();
        Person person = (Person) session.getAttribute("name");
        resp.getWriter().write(person.toString());
        System.out.println(person.toString());


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

註冊Servlet測試存取
(1)存取設定資訊s1

(2)存取得到資訊s2

2.對談過期

  • 手動

    public class SessionDemon03 extends HttpServlet {
    
            //登出,移除
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            HttpSession session = req.getSession();
            session.removeAttribute("name");
            //手動登出session
            session.invalidate();//一旦登出會重新產生一個sessionId
            
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  • 自動

    <!--設定session預設失效時間-->
      <session-config>
    <!--15分鐘後session自動失效,以分鐘為單位-->
        <session-timeout>15</session-timeout>
      </session-config>
    

最後我們再回到剛開始的問題,一個網站怎麼證明你來過呢?

思考 : Session和Cookie的區別

①cookie可以儲存在瀏覽器或者本地,Session只能存在伺服器
②session能夠儲存任意的java物件,cookie 只能儲存String 型別的物件
③Session比tCookie更具有安全性(Cookie有安全隱患,通過攔截或本地檔案找得到你的cookie後可以進行攻擊)
④Session佔用伺服器效能,Session過多,增加伺服器壓力
⑤單個Cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個Cookie,Session是沒有大小限制和伺服器的

到這裡關於Cookie與Session的知識就結束啦≧ω≦,希望對大家有所幫助!

大家覺得文章還可以的話可以點個推薦支援博主啊 (u‿ฺu✿ฺ)