如何避免在第一次调用页面时出现 ;jsessionid=XXX?如果第一页是jsp,它可以工作
Posted
技术标签:
【中文标题】如何避免在第一次调用页面时出现 ;jsessionid=XXX?如果第一页是jsp,它可以工作【英文标题】:How to avoid ;jsessionid=XXX on the first call to a page? it works if first page is jsp 【发布时间】:2012-07-06 03:17:14 【问题描述】:我有一个使用带有<iframe></iframe>
的欢迎页面 index.jsp 的应用程序,iframe 的内容是一个 jsf 页面。如果我访问 index.jsp,我会在第一次进入 firebug 时看到一个 cookie:
Set-Cookie JSESSIONID=C615DA89B6EF73F801973EA3DCD3B226; Path=/
<iframe>
的页面继承了这个jsessionid。但是:当我直接访问<iframe/>
的页面时,我会在第一次请求时将 jsessionId 重写为所有没有 cookie 的 URL。之后使用 cookie。这一切都很好 - 如果:
安全系统将允许我执行 url 重写。
我运行 jboss 4.2.2
我想实现与 index.jsp 相同的行为 - 例如始终使用 cookie 并始终避免 http 重写。
[编辑] 感谢 balusc 的回答,我写了这个:
public class JsessionIdAvoiderFilter implements Filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException
boolean allowFilterChain = redirectToAvoidJsessionId((HttpServletRequest) req, (HttpServletResponse)res);
//I'm doing this because if I execute the request completely, it will perform a pretty heavy lookup operation. No need to do it twice.
if(allowFilterChain)
chain.doFilter(req, res);
public static boolean redirectToAvoidJsessionId(HttpServletRequest req, HttpServletResponse res)
HttpSession s = req.getSession();
if(s.isNew())
//after the redirect we don't want to redirect again.
if(!(req.isRequestedSessionIdFromCookie()&&req.isRequestedSessionIdFromURL()))
//yeah we have request parameters actually on that request.
String qs = req.getQueryString();
String requestURI = req.getRequestURI();
try
res.sendRedirect(requestURI+"?"+qs);
return false;
catch (IOException e)
logger.error("Error sending redirect. " + e.getMessage());
return true;
别忘了将它添加到您的web.xml
<filter>
<display-name>JsessionId Filter</display-name>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<filter-class>my.namespace.JsessionIdAvoiderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
【问题讨论】:
【参考方案1】:从 Servlet 3.0 开始,您可以为此使用 <tracking-mode>COOKIE</tracking-mode>
。但由于 JBoss 4.2.2 不兼容 Servlet 3.0,所以这不是一个选项。
最简单的方法是创建一个 servlet 过滤器,当 HttpSession#isNew()
返回 true
时,该过滤器将重定向发送到 HttpServletRequest#getRequestURI()
。当客户端根本不支持 cookie 时,不要忘记检查 HttpServletRequest#isRequestedSessionIdFromCookie()
以防止无限重定向循环。
【讨论】:
谢谢。您的网站上某处是否有“捐赠善良幸运猪”?我可以给你点披萨吗? 不客气。在我的网站/博客的右侧栏中,您可以找到一个贝宝捐赠按钮。这是迄今为止唯一的方法。 好像我不能给你发私人信息。你应该弄清楚如何强制贝宝是英文的。那个荷兰语有点令人困惑:-)“Snel doneren”:-D 哦,对我来说只是英文?我去看看。 编写一个覆盖HttpServletRequest.encodeURL
和 HttpServletRequest.encodeRedirectURL
的过滤器来简单地返回传递给它的 String
参数会更简单:不需要重定向,你最终会禁用 URL - 编码的会话 ID(并且需要 cookie)。【参考方案2】:
根据克里斯托弗·舒尔茨的建议,我尝试了这个并且它有效。
package com.rama.test.jsessionfilter
public class JsessionIdAvoiderFilter implements Filter
protected static final Logger LOGGER = LogManager.getLogger(JsessionIdAvoiderFilter.class);
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException
if (!(req instanceof HttpServletRequest))
chain.doFilter(req, res);
return;
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// Redirect requests with JSESSIONID in URL to clean old links
/* If you really want clean up some old links which have Jsession id bookmarked clean it. If its new app
this below check is not required. */
if (request.isRequestedSessionIdFromURL())
String url = request.getRequestURL().append(request.getQueryString() != null ? "?"
+ request.getQueryString() : "").toString();
response.setHeader("Location", url);
response.sendError(HttpServletResponse.SC_MOVED_PERMANENTLY);
LOGGER.info(" Found url with jsession id in it:"+ request.getRequestURL() +": url="+url);
return;
// Prevent rendering of JSESSIONID in URLs for all outgoing links
HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(
response)
@Override
public String encodeRedirectUrl(String url)
return url;
@Override
public String encodeRedirectURL(String url)
return url;
@Override
public String encodeUrl(String url)
return url;
@Override
public String encodeURL(String url)
return url;
;
chain.doFilter(req, wrappedResponse);
public void destroy()
public void init(FilterConfig arg0) throws ServletException
以及 web.xml 中的以下条目
<filter>
<display-name>JsessionId Filter</display-name>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<filter-class>com.rama.test.jsessionfilter.JsessionIdAvoiderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
效果很好!!!。
【讨论】:
如果 cookie 被禁用,您最好检查您的代码并发出警告。假设是在客户端启用了 cookie。【参考方案3】:这可以通过一个简单的过滤器来完成,该过滤器使用覆盖 HttpServletRequest.encodeURL 和 HttpServletRequest.encodeRedirectURL 的 HttpServletRequest 包装请求。只需返回传递给它的 String 参数,您将禁用 URL 重写。请注意,这仅适用于单个 Web 应用,除非您想在 conf/web.xml
中配置它(不推荐)或在所有单独的 Web 应用中配置它。
此技术优于您问题后面发布的技术,因为它不需要重定向,这会减慢您的请求。 IMO,它也更干净。
【讨论】:
我会尽快看看。你对“单一”网络应用程序是什么意思?我不太清楚你的意思 过滤器在WEB-INF/web.xml
中配置,它只会保护描述的一个webapp。
我接受 balusc 答案的原因是因为这是我实施的,它非常适合所描述的问题 - 我没有时间尝试你的解决方案,但听起来不错以上是关于如何避免在第一次调用页面时出现 ;jsessionid=XXX?如果第一页是jsp,它可以工作的主要内容,如果未能解决你的问题,请参考以下文章
如何避免在 jQuery 动画 [fadeIn() 或 animate()] 结束时出现文本闪烁?
SpriteKit:如何添加/删除节点并避免枚举时出现突变异常?