我有一个应用程序使用欢迎页面index.jsp与<iframe></iframe>
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>
从Servlet 3.0开始,您可以使用<tracking-mode>COOKIE</tracking-mode>
。但由于JBoss 4.2.2不是Servlet 3.0的编译,因此这不是一个选择。
最简单的方法是创建一个servlet过滤器,当HttpServletRequest#getRequestURI()
返回HttpSession#isNew()
时,它会向true
发送重定向。当客户端根本不支持cookie时,不要忘记检查HttpServletRequest#isRequestedSessionIdFromCookie()
以防止无限重定向循环。
基于克里斯托弗舒尔茨的建议,我试过这个并且它有效。
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>
工作得很棒!!!
这可以通过一个简单的Filter完成,该Filter使用HttpServletRequest包装请求,HttpServletRequest覆盖HttpServletRequest.encodeURL和HttpServletRequest.encodeRedirectURL。只需返回传递给它的String参数,您将禁用URL重写。请注意,这只适用于单个Web应用程序,除非您要在conf/web.xml
中配置它(不推荐)或在所有单独的Web应用程序中配置它。
此技术优于您在问题中稍后发布的技术,因为它不需要重定向,这可能会降低您的请求速度。 IMO,它也更清洁。