您好,登录后才能下订单哦!
禁用Cookie后Session该怎么样使用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
Session在浏览器关闭之后就失效
其实本质上是浏览器在关闭之后,应用对应的SessionCookie被清除了,再次打开浏览器请求应用时,之前的SessionId对应的Cookie不存在,所以就会重新创建一个Session。而服务端原来的Session其实还是存在的,只是没人与之对应,就默默的等着超时时间一到,被清除了。
而对于Cookie,我们都知道其是浏览器保存客户端本地的,安全问题暂且不说,但Cookie是可以在浏览器中配置后关闭的。关闭之后,服务器就不能再向浏览器写Cookie的,此时我们基于SessionCookie的实现方式就遇到了问题。
虽然每一次仍然通过response将Set-Cookie添加到header里,但发到浏览器的时候,不能再写Cookie,后续的请求依然是重新发一个sessionId为null的请求,导致每次仍是重新创建session对象,并没有解决交互状态的问题。
为了解决这个问题,服务器提供了另外一种方式:
URL重写,即英文的URLrewrite。
这一方式,其本质上是在每次请求的url后面append 上一个类似于jsessionid=xxxx这样的参数,在服务端解析时,获取到jsessionid对应的值,并根据其获取到对应的Session对象,从而保证了交互状态一致。
一句话就说明白了。
但这一句话背后,有一些事情还是需要注意的,
例如,我们可以自己在url后面写上jsessionid=当前session的id值。这种类似于硬编码,因为服务端获取这个session的id是通过jsessionid这个参数名来获取的,而这个参数我们在前一篇文章中了解到,是可以配置的,当改了之后,后面的sessionId就获取不到了。
其次,为了保证各类url规则的一致,服务端提供了response API来处理,只需要直接使用,就可以完成jsessionid的参数追加。
/**
* Encode the session identifier associated with this response
* into the specified URL, if necessary.
*
* @param url URL to be encoded
*/
@Override
public String encodeURL(String url) {
String absolute;
try {
absolute = toAbsolute(url);
} catch (IllegalArgumentException iae) {
// Relative URL
return url;
}
if (isEncodeable(absolute)) {//关键在这里
// W3c spec clearly said
if (url.equalsIgnoreCase("")) {
url = absolute;
} else if (url.equals(absolute) && !hasPath(url)) {
url += '/';
}
return (toEncoded(url, request.getSessionInternal().getIdInternal()));
} else {
return (url);
}
}
我们看代码中的实现逻辑:
/**
* Return <code>true</code> if the specified URL should be encoded with
* a session identifier. This will be true if all of the following
* conditions are met:
* <ul>
* <li>The request we are responding to asked for a valid session
* <li>The requested session ID was not received via a cookie
* <li>The specified URL points back to somewhere within the web
* application that is responding to this request
* </ul>
*
* @param location Absolute URL to be validated
*/
protected boolean isEncodeable(final String location) {
if (location == null) {
return (false);
}
// Is this an intra-document reference?
if (location.startsWith("#")) {
return (false);
}
// Are we in a valid session that is not using cookies?
final Request hreq = request;
final Session session = hreq.getSessionInternal(false);
if (session == null) {
return (false);
}
if (hreq.isRequestedSessionIdFromCookie()) {
return (false);
}
// Is URL encoding permitted
if (!hreq.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.URL)) {
return false;
}
return doIsEncodeable(hreq, session, location);
}
代码中会根据是否使用SessionCookie来决定是否要继续,
之后会继承判断可使用的Session tracking Mode里都有哪些,是否包含URL。
在doIsEncodeable方法中,最终实现是这一行代码
String tok = ";" +
SessionConfig.getSessionUriParamName(request.getContext()) +
"=" + session.getIdInternal();
也就是我们上面提到的硬编码jsessionid到url后面不太好的原因,这里就是在读取它的配置。
public static String getSessionUriParamName(Context context) {
String result = getConfiguredSessionCookieName(context);
if (result == null) {
result = DEFAULT_SESSION_PARAMETER_NAME;
}
return result;
}
另外,我们上面提到的Session tracking Mode,是在Tomcat启动的时候判断的,而服务端并不可能得知以后要连接的浏览器中,哪些是不允许Cookie的,所以对于Sesion tracking mode,URL无论如何都是可以使用的,而Session cookie是否要使用,是通过在Context组件中配置的其cookies属性为false时禁止的
private void populateSessionTrackingModes() {
// URL re-writing is always enabled by default
defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
supportedSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
if (context.getCookies()) { //此处读取Context组件的cookies配置,如果为false,则不使用SessionCookie
defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE);
supportedSessionTrackingModes.add(SessionTrackingMode.COOKIE); }
总结下,即为了防止客户端禁用Cookie导致的Session状态不一致的情况,我们可以采用UrlRewrite的方式来保证。
这一过程,我们可以使用response的encodeURL方法来使sessionid添加到url后面,不过是需要先在Context组件中声明不使用cookies。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。