禁止 Cookie 使用 Session,採用 URL 重寫,具體解決方案

先敘述一下 session 的實現原理吧!

session 服務器爲每個客戶端訪問開闢的一塊內存區域,可以存放一些客戶端的一些操作信息

正常情況下在用戶通過客戶端訪問服務器這個過程中 session 一直存活,直到客戶端關閉,服務器中的 session 被銷燬

非正常情況下,服務器調用 session.invalidate() 方法進行手動銷燬

session 依賴於 cookie !!!

沒有 cookie 是無法通過 request.getSession() 獲取對應的客戶端的 session 的

具體實現原理

客戶端第一次訪問服務器,服務器返回

 在服務器返回的響應頭中,可以看到 Set-Cookie 字段,這個字段中,JSESSION=94E09A118319882388C08A27A42696DB

94E09A118319882388C08A27A42696DB 爲服務器保存的 session 對應的 ID

當客戶端再訪問該網站的其他鏈接 👇

服務器的響應頭則不會再有 Set-Cookie 字段了👆

但是再看客戶端的請求頭 👇

 會自動的將 JSESSIONID 這個 Cookie 帶上 👆,服務器根據該字段對應的值就可以拿到該客戶端保存在服務器的 session 對象

此時可以通過 request.getSession() 獲得對應的 session 對象

然而這都是基於客戶端沒有禁止 Cookie 的情況下,當客戶端禁止了 Cookie ,當訪問服務器的其他鏈接,將不會攜帶 Cookie 了,此時又該怎麼辦呢?(*^_^*)

解決辦法之一:將 jsessionid 這個保存在客戶端的值拼接在對應的 url 上,這樣服務器可以通過解析 url 將 jsessionid 對應的值取出來,然後通過這個 sessionId 去獲取保存在服務器中的 session 實例對象

通過 HttpServletResponse response,response.encodeURL() 方法進行將對應的 jsessionid 拼進去

現在說一下 response.encodeURL() 該函數的作用吧

首先判斷客戶端是否禁止了 Cookie ,如果沒有禁止,則返回 request.getRequestURI() 這個的值不會拼接上 jsessionid

如果判斷客戶端禁止了 Cookie, 則會在 request.getContextPath()+"/hello/index" 後拼接上 jsessionid=xxx 👇

當再訪問服務器時,鏈接上拼上了 jsessionid 值 👇

 

客戶端禁止了 Cookie ,所以請求頭中 Cookie 值並沒有帶上 👆

然後就可以通過服務器解析對應的 url 獲取 jsessionid 獲取對應的 sessionId, 然後根據 sessionId 查詢服務器對應的 session 實例對象 👇

 

基本的原理已經講的差不多了,現在給出一個基於 SpringBoot 的一個解決方案,獲取 session 的

MySessionContext 代碼

package mr.s.javaee.context;

import javax.servlet.http.HttpSession;
import java.util.HashMap;

public class MySessionContext {

    private static MySessionContext instance;
    private HashMap<String,HttpSession> sessionMap;

    private MySessionContext() {
        sessionMap = new HashMap<String,HttpSession>();
    }

    public static MySessionContext getInstance() {
        if (instance == null) {
            instance = new MySessionContext();
        }
        return instance;
    }

    public synchronized void addSession(HttpSession session) {
        if (session != null) {
            sessionMap.put(session.getId(), session);
        }
    }

    public synchronized void delSession(HttpSession session) {
        if (session != null) {
            sessionMap.remove(session.getId());
        }
    }

    public synchronized HttpSession getSession(String sessionID) {
        if (sessionID == null) {
            return null;
        }
        return sessionMap.get(sessionID);
    }
}

SessionListener 代碼

package mr.s.javaee.listener;

import mr.s.javaee.context.MySessionContext;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class SessionListener implements HttpSessionListener {

    private MySessionContext myc = MySessionContext.getInstance();

    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        myc.addSession(session);
    }

    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        myc.delSession(session);
    }
}

最後需要修改一下,啓動類!加上 @ServletComponentScan 註解 👇

具體獲得 session 的核心代碼

String uri = request.getRequestURI();
String sessionId = uri.split("jsessionid=")[1];
System.out.println(sessionId);
MySessionContext myc= MySessionContext.getInstance();
HttpSession session = myc.getSession(sessionId);
String name = session.getAttribute("name").toString();

本篇到此結束了,謝謝瀏覽

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章