禁止 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();

本篇到此结束了,谢谢浏览

发布了92 篇原创文章 · 获赞 23 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/assiduous_me/article/details/98469842