java web中, 用session来表示用户浏览器(客户端)与服务器建立的一次会话。
通常用sessionId来标记一个session,在Java中,有很简单的方式直接获取sessionId;
HttpSession session = request.getSession(); String sessionId = session.getId();
但是sessionId并不是session的特性,实际上,sessionId是在客户端首次创建会话时将生成的sessionId存入cookie中,在之后的访问中直接读取这个id值。
当客户端禁止了cookie行为后,SessionId在每次刷新页面时都会更新,利用id来表示会话也成为了妄想,此篇文章意在说明,如何操作能使SessionId能够独立于cookie使用。
这种操作其实在shiro中已经被应用了,当我们进入登录页面中,url后会出现";jssionid=xxxxxx",将sessionid显示的标注在url中,可以使用:
response.encodeURL(url);
当cookie被禁用时,该方法会在url后面添加字符,返回一个带有sessionid的url字符串,Java中会自动从中获取sessionId,可以直接使用如下方法处理我们要做转发的请求url:
response.encodeRedirectURL(request.getRequestURI());
注意,encodeURL底层中核心逻辑代码是这样的:
@Override
public String encodeURL(String url) {
//绝对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);
}
}
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;
//这里的false指若session为空,不自动生成session
final Session session = hreq.getSessionInternal(false);
//这里session
if (session == null) {
return false;
}
//判断如果session来自cookie,则不作url处理
if (hreq.isRequestedSessionIdFromCookie()) {
return false;
}
// Is URL encoding permitted
if (!hreq.getServletContext().getEffectiveSessionTrackingModes().
contains(SessionTrackingMode.URL)) {
return false;
}
if (SecurityUtil.isPackageProtectionEnabled()) {
return (
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run(){
return Boolean.valueOf(doIsEncodeable(hreq, session, location));
}
})).booleanValue();
} else {
return doIsEncodeable(hreq, session, location);
}
}
很多版本的包中,判断session是否为空时,并没有生成新的session,若是用户禁止cookie,程序中也不会生成session,最终还是不能正确的做请求跳转,所以在跳转前,先做request.getSession()处理。
获取url之后,我们要手动处理逻辑,可以使用拦截器进行统一内容处理,在拦截器中:
request.getSession(true);
String url=response.encodeURL(request.getRequestURI());
//不作处理会死循环
if(!url.equals(request.getRequestURI())){
try {
response.sendRedirect(url);
} catch (IOException e) {
//do something
}
}else{
}

