如何避免在第一次调用页面时出现 ;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 开始,您可以为此使用 &lt;tracking-mode&gt;COOKIE&lt;/tracking-mode&gt;。但由于 JBoss 4.2.2 不兼容 Servlet 3.0,所以这不是一个选项。

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

【讨论】:

谢谢。您的网站上某处是否有“捐赠善良幸运猪”?我可以给你点披萨吗? 不客气。在我的网站/博客的右侧栏中,您可以找到一个贝宝捐赠按钮。这是迄今为止唯一的方法。 好像我不能给你发私人信息。你应该弄清楚如何强制贝宝是英文的。那个荷兰语有点令人困惑:-)“Snel doneren”:-D 哦,对我来说只是英文?我去看看。 编写一个覆盖 HttpServletRequest.encodeURLHttpServletRequest.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:如何添加/删除节点并避免枚举时出现突变异常?

如何避免在 iOS 中使用 Facebook SDK 时出现“重复状态消息”错误?

若依vue项目部署步骤,避免刷新时出现404错误

android,在先做了popStack之后,如何避免用FragmentTransaction替换片段时出现闪烁