resin的session id reuse特性(2)--分析問(wèn)題
上文中詳細(xì)描述了問(wèn)題的表現(xiàn)情況,由于這個(gè)特性嚴(yán)重影響到目前為公司設(shè)計(jì)的一套前臺(tái)統(tǒng)一認(rèn)證方案,因此不得不特別關(guān)注。好在resin的源代碼是公開(kāi)的,直接從resin的官網(wǎng)將resin的源代碼拿下來(lái),看resin到底是如何處理的。首先找到com.caucho.server.http.HttpRequest,發(fā)現(xiàn)是extends AbstractHttpRequest
在AbstractHttpRequest中找到方法
public HttpSession getSession(boolean create)
發(fā)現(xiàn)調(diào)用
_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);
打開(kāi)com.caucho.server.session.SessionManager的createSession()方法,
發(fā)現(xiàn)有注釋?zhuān)?@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);
if (id == null || id.length() < 4 ||
! isInSessionGroup(id) || ! reuseSessionId(fromCookie)) {
id = createSessionId(request, true);
}
SessionImpl session = create(id, now, true);
我們關(guān)注! reuseSessionId(fromCookie)這句,打開(kāi)看函數(shù)
/**
* 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;
}
* 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的這種代碼風(fēng)格,一般我寧可寫(xiě)成下面的這種,看代碼時(shí)容易理解
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));
}
并且可以看到默認(rèn)值為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));
}
private int _reuseSessionId = COOKIE;
翻一下resin的文檔,可以發(fā)現(xiàn)在resin.conf的<session-config>有reuse-session-id這個(gè)配置項(xiàng),resin文檔的說(shuō)明如下:
"reuse-session-id defaults to true so that Resin can share the session id amongst different web-apps."
默認(rèn)情況下reuse-session-id設(shè)置為true,setReuseSessionId("true")會(huì)使得_reuseSessionId=COOKIE,而reuseSessionId()方法中的表達(dá)式可以簡(jiǎn)化:
(reuseSessionId == TRUE) || (fromCookie && (reuseSessionId == COOKIE));
--> (COOKIE == TRUE) || (fromCookie && (COOKIE == COOKIE))
--> (false) || (fromCookie && true)
--> fromCookie
因此默認(rèn)情況下jsessionid用cookie傳遞就可以做到重用,否則就要生成新的jsessionid.
按照這個(gè)思路,只要將reuse-session-id配置項(xiàng)設(shè)置為"all",就可以做到即使使用url rewrite也可以重用jsessionid.
ok,問(wèn)題解決
posted on 2007-12-28 12:01 sky ao 閱讀(1703) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): web