15

我有一个应用程序,它使用欢迎页面 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> 
4

3 回答 3

14

从 Servlet 3.0 开始,您可以使用<tracking-mode>COOKIE</tracking-mode>它。但由于 JBoss 4.2.2 不是 Servlet 3.0 兼容的,所以这不是一个选项。

最简单的方法是创建一个 servlet 过滤器,它在返回HttpServletRequest#getRequestURI()时发送重定向。当客户端根本不支持 cookie 时,不要忘记检查以防止无限重定向循环。HttpSession#isNew()trueHttpServletRequest#isRequestedSessionIdFromCookie()

于 2012-07-05T19:00:58.827 回答
3

根据克里斯托弗舒尔茨的建议,我尝试了这个并且它有效。

    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>

效果很好!!!!

于 2013-11-04T21:21:00.430 回答
2

这可以通过一个简单的过滤器来完成,该过滤器使用覆盖 HttpServletRequest.encodeURL 和 HttpServletRequest.encodeRedirectURL 的 HttpServletRequest 包装请求。只需返回传递给它的 String 参数,您将禁用 URL 重写。请注意,这仅适用于单个 webapp,除非您想在conf/web.xml(不推荐)中配置它或在所有单独的 webapps 中配置它。

这种技术优于您问题后面发布的技术,因为它不需要重定向,这会减慢您的请求。IMO,它也更清洁。

于 2012-07-09T13:57:54.950 回答