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解决方案