上文中詳細描述了問題的表現情況,由于這個特性嚴重影響到目前為公司設計的一套前臺統一認證方案,因此不得不特別關注。好在resin的源代碼是公開的,直接從resin的官網將resin的源代碼拿下來,看resin到底是如何處理的。
首先找到com.caucho.server.http.HttpRequest,發現是extends AbstractHttpRequest
在AbstractHttpRequest中找到方法
public HttpSession getSession(boolean create)
發現調用
_session = createSession(create, hasOldSession);
這里有一段注釋解釋了重用jsessonid的行為:
Must accept old ids because different applications in the same server must share the same cookie
But, if the session group doesn't match, then create a new session.
在createSession方法中找到
manager.createSession(id, now, this, _isSessionIdFromCookie);
打開com.caucho.server.session.SessionManager的createSession()方法,
發現有注釋: @param oldId the id passed to the request. Reuse if possible.
看代碼:
String id = oldId;
if (id == null || id.length() < 4 ||
! isInSessionGroup(id) || ! reuseSessionId(fromCookie)) {
id = createSessionId(request, true);
}
SessionImpl session = create(id, now, true);
我們關注! reuseSessionId(fromCookie)這句,打開看函數
/**
* True if the server should reuse the current session id if the
* session doesn't exist.
*/
public boolean reuseSessionId(boolean fromCookie)
{
int reuseSessionId = _reuseSessionId;
return reuseSessionId == TRUE || fromCookie && reuseSessionId == COOKIE;
}
注:非常不喜歡resin的這種代碼風格,一般我寧可寫成下面的這種,看代碼時容易理解
return (reuseSessionId == TRUE) || (fromCookie && (reuseSessionId == COOKIE));
再看
/**
* True if the server should reuse the current session id if the
* session doesn't exist.
*/
public void setReuseSessionId(String reuse)
throws ConfigException
{
if (reuse == null)
_reuseSessionId = COOKIE;
else if (reuse.equalsIgnoreCase("true") ||
reuse.equalsIgnoreCase("yes") ||
reuse.equalsIgnoreCase("cookie"))
_reuseSessionId = COOKIE;
else if (reuse.equalsIgnoreCase("false") || reuse.equalsIgnoreCase("no"))
_reuseSessionId = FALSE;
else if (reuse.equalsIgnoreCase("all"))
_reuseSessionId = TRUE;
else
throw new ConfigException(L.l("'{0}' is an invalid value for reuse-session-id. 'true' or 'false' are the allowed values.",
reuse));
}
并且可以看到默認值為COOKIE
private int _reuseSessionId = COOKIE;
翻一下resin的文檔,可以發現在resin.conf的<session-config>有reuse-session-id這個配置項,resin文檔的說明如下:
"reuse-session-id defaults to true so that Resin can share the session id amongst different web-apps."
默認情況下reuse-session-id設置為true,setReuseSessionId("true")會使得_reuseSessionId=COOKIE,而reuseSessionId()方法中的表達式可以簡化:
(reuseSessionId == TRUE) || (fromCookie && (reuseSessionId == COOKIE));
--> (COOKIE == TRUE) || (fromCookie && (COOKIE == COOKIE))
--> (false) || (fromCookie && true)
--> fromCookie
因此默認情況下jsessionid用cookie傳遞就可以做到重用,否則就要生成新的jsessionid.
按照這個思路,只要將reuse-session-id配置項設置為"all",就可以做到即使使用url rewrite也可以重用jsessionid.
ok,問題解決