如何避免;第一次调用页面时jsessionid = XXX?如果第一页是jsp,它可以工作

问题描述 投票:15回答:3

我有一个应用程序使用欢迎页面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> 
jsf tomcat cookies jboss jsessionid
3个回答
13
投票

从Servlet 3.0开始,您可以使用<tracking-mode>COOKIE</tracking-mode>。但由于JBoss 4.2.2不是Servlet 3.0的编译,因此这不是一个选择。

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


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>

工作得很棒!!!


2
投票

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

此技术优于您在问题中稍后发布的技术,因为它不需要重定向,这可能会降低您的请求速度。 IMO,它也更清洁。

© www.soinside.com 2019 - 2024. All rights reserved.