java通过sessionID获取指定session,jetty通过sessionID获取指定session,Jetty的session源码分析

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录

写在前面

session+cookie的机制相信很多小伙伴都明白这里就不再赘述了。

我们都知道浏览器请求的信息中会自动将jsessionid传给服务端。

传统方式通过HttpSession session = request.getSession(); 方式就可以获取到一个HttpSession那么我们如何能通过sessionId来获取到指定用户的session呢

jetty环境源码分析

本文的运行web环境是jetty环境tomcat估计同理应该大差不差。

其实HttpServletRequest、HttpServletResponse、HttpSession不管在jetty、tomcat还是其他web容器中都有一个基本的实现类而我们通过request.getSession()方式获取session就是调用了org.eclipse.jetty.server.Request类的getSession()方法

// org.eclipse.jetty.server.Request#getSession()
/*
 * @see javax.servlet.http.HttpServletRequest#getSession()
 */
@Override
public HttpSession getSession()
{
    return getSession(true);
}

/*
 * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
 */
@Override
public HttpSession getSession(boolean create)
{
    if (_session != null)
    {
        if (_sessionHandler != null && !_sessionHandler.isValid(_session))
            _session = null;
        else
            return _session;
    }

    if (!create)
        return null;

    if (getResponse().isCommitted())
        throw new IllegalStateException("Response is committed");

    if (_sessionHandler == null)
        throw new IllegalStateException("No SessionManager");

    _session = _sessionHandler.newHttpSession(this); // 创建session
    if (_session == null)
        throw new IllegalStateException("Create session failed");
    
    HttpCookie cookie = _sessionHandler.getSessionCookie(_session, getContextPath(), isSecure());
    if (cookie != null)
        _channel.getResponse().replaceCookie(cookie);

    return _session;
}

我们可以看到jetty的源码获取session时进行了判断如果获取的session为空就默认新建一个session创建session是通过_sessionHandler创建的而_sessionHandler是什么东西呢

private SessionHandler _sessionHandler;
// org.eclipse.jetty.server.session.SessionHandler#newHttpSession
public HttpSession newHttpSession(HttpServletRequest request)
{
    long created = System.currentTimeMillis();
    String id = _sessionIdManager.newSessionId(request, created); // 创建sessionid
    Session session = _sessionCache.newSession(request, id, created, (_dftMaxIdleSecs > 0 ? _dftMaxIdleSecs * 1000L : -1)); // 创建新的session
    session.setExtendedId(_sessionIdManager.getExtendedId(id, request));
    session.getSessionData().setLastNode(_sessionIdManager.getWorkerName());

    try
    {
        _sessionCache.add(id, session); // 将session放入缓存
        Request baseRequest = Request.getBaseRequest(request);
        baseRequest.setSession(session);
        baseRequest.enterSession(session);
        _sessionsCreatedStats.increment();

        if (request != null && request.isSecure())
            session.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE);

        callSessionCreatedListeners(session);

        return session;
    }
    catch (Exception e)
    {
        LOG.warn(e);
        return null;
    }
}

通过以上源码我们可以看出session创建完毕后会将session放入_sessionCache这个_sessionCache是什么呢

SessionCache的基本默认实现是DefaultSessionCache里面存储的session都是用ConcurrentHashMap存储的key是sessionidvalue是session对象

protected ConcurrentHashMap<String, Session> _sessions = new ConcurrentHashMap<>();

我们继续回到SessionHandler看着像是session专用的处理器发现里面有这样一个方法通过id获取session正是我们想要的

// org.eclipse.jetty.server.session.SessionHandler#getSession
public Session getSession(String id)
{
    try
    {
        Session session = _sessionCache.get(id);
        if (session != null)
        {
            //If the session we got back has expired
            if (session.isExpiredAt(System.currentTimeMillis()))
            {
                //Expire the session
                try
                {
                    session.invalidate();
                }
                catch (Exception e)
                {
                    LOG.warn("Invalidating session {} found to be expired when requested", id);
                    LOG.warn(e);
                }

                return null;
            }

            session.setExtendedId(_sessionIdManager.getExtendedId(id, null));
        }
        return session;
    }
    catch (UnreadableSessionDataException e)
    {
        LOG.warn("Error loading session {}", id);
        LOG.warn(e);
        try
        {
            //tell id mgr to remove session from all other contexts
            getSessionIdManager().invalidateAll(id);
        }
        catch (Exception x)
        {
            LOG.warn("Error cross-context invalidating unreadable session {}", id);
            LOG.warn(x);
        }
        return null;
    }
    catch (Exception other)
    {
        LOG.warn(other);
        return null;
    }
}

此时我们只需要能得到这个SessionHandler就能通过id获取我们想要的session啦

我发现org.eclipse.jetty.server.Request有个getSessionHandler方法正好符合我们的预期

public SessionHandler getSessionHandler()
{
    return _sessionHandler;
}

此时大功告成

根据sessionID获取指定Session

根据上面的分析我们可以获取我们想要的Session了

String sessionId = "sessionid";
if(request instanceof org.eclipse.jetty.server.Request){
    // 根据sessionId获取指定Session
    Session session = ((org.eclipse.jetty.server.Request) request).getSessionHandler().getSession(sessionId);
}

此时我们可以为所欲为了~

写在后面

cookie技术基本算是一个 过时的技术了很多框架都是通过token+spring session的方式做session共享和前后端登录态的验证。

而spring session更是对session做了进一步的封装使用起来更加的方便
spring-session的使用及其原理——分布式session解决方案

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java

“java通过sessionID获取指定session,jetty通过sessionID获取指定session,Jetty的session源码分析” 的相关文章