Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Tiles时,Spring会话在Tomcat 8上不工作-会话Cookie未设置为已包含响应_Spring_Tomcat_Spring Boot_Tomcat8_Spring Session - Fatal编程技术网

使用Tiles时,Spring会话在Tomcat 8上不工作-会话Cookie未设置为已包含响应

使用Tiles时,Spring会话在Tomcat 8上不工作-会话Cookie未设置为已包含响应,spring,tomcat,spring-boot,tomcat8,spring-session,Spring,Tomcat,Spring Boot,Tomcat8,Spring Session,我在一个SpringBoot项目上使用SpringSession1.2.0.RELEASE。这被打包为war并部署在Tomcat8上 我遵循了Spring会话文档并正确地配置了它。问题在于,应用程序的入口点是一个控制器,该控制器在会话上设置一些值,但会话cookie不会发送到浏览器 我看到: org.springframework.session.web.http.CookieHttpSessionStrategy.onNewSession()尝试编写cookie: this.cookieSer

我在一个SpringBoot项目上使用SpringSession1.2.0.RELEASE。这被打包为war并部署在Tomcat8上

我遵循了Spring会话文档并正确地配置了它。问题在于,应用程序的入口点是一个控制器,该控制器在会话上设置一些值,但会话cookie不会发送到浏览器

我看到:

  • org.springframework.session.web.http.CookieHttpSessionStrategy.onNewSession()
    尝试编写cookie:

    this.cookieSerializer
    .writeCookieValue(新的CookieValue(请求、响应、CookieValue))

  • org.springframework.session.web.http.DefaultCookieSerializer.writeCookieValue()
    在响应中设置cookie:

    response.addCookie(sessioncokie)

  • 曲奇并不是真的写出来的。底层响应对象是org.apache.catalina.core.ApplicationHttpResponse。它的
    addCookie()
    方法是:

    /**
      *  Disallow <code>addCookie()</code> calls on an included response.         
      *  @param cookie The new cookie
      */
    @Override
    public void addCookie(Cookie cookie) {
    
        if (!included)
            ((HttpServletResponse) getResponse()).addCookie(cookie);
    
    }
    
  • 问题在于
    included
    属性,该属性在某个点被设置为true,从而阻止添加cookie

    当jsp(使用tiles)正在接受服务时会发生这种情况:

    更新:

    此时响应被标记为包含(standard.jsp tiles layout插入属性时:


    为了解决这个问题,我最终创建了一个过滤器来强制创建会话

    如图所示,对控制器的第一次调用没有添加cookie,因为在Tiles JSP呈现期间,响应已经标记为包含。我所做的是在筛选器中强制创建会话,并重定向请求相同的requestURI。这样,因为调用不涉及呈现cookie的Tiles,所以创建cookie并在接下来的通话中可以立即使用

    @Bean
    @ConditionalOnExpression("${sessionEnforcerFilter.enabled:true}")
    public FilterRegistrationBean sessionEnforcerFilter(){
        logger.info("Registering sessionEnforcerFilter");
        FilterRegistrationBean frb = new FilterRegistrationBean();
        frb.setName("sessionEnforcerFilter");
        frb.setFilter(new SessionEnforcerFilter());
        frb.setUrlPatterns(Arrays.asList(new String[]{"/*"}));
        return frb;
    }
    
    public class SessionEnforcerFilter implements Filter{
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {}
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
            HttpServletRequest httpServletRequest = (HttpServletRequest)request;
            HttpServletResponse httpServletResponse = (HttpServletResponse)response;
            if(httpServletRequest.getSession(false)==null){
                logger.debug("sessionEnforcerFilter.doFilter () - Session is null - forcing its creation");
                httpServletRequest.getSession();
                String requestURI = httpServletRequest.getRequestURI();
                logger.debug("sessionEnforcerFilter.doFilter () - Repeating request [{}]", requestURI);
                httpServletResponse.sendRedirect(requestURI);
            }else{
                chain.doFilter(httpServletRequest, response);
            }
        }
    
        @Override
        public void destroy() {}
    
    }
    

    为了解决这个问题,我最终创建了一个过滤器来强制创建会话

    如图所示,对控制器的第一次调用没有添加cookie,因为在Tiles JSP呈现期间,响应已经标记为包含。我所做的是在筛选器中强制创建会话,并重定向请求相同的requestURI。这样,因为调用不涉及呈现cookie的Tiles,所以创建cookie并在接下来的通话中可以立即使用

    @Bean
    @ConditionalOnExpression("${sessionEnforcerFilter.enabled:true}")
    public FilterRegistrationBean sessionEnforcerFilter(){
        logger.info("Registering sessionEnforcerFilter");
        FilterRegistrationBean frb = new FilterRegistrationBean();
        frb.setName("sessionEnforcerFilter");
        frb.setFilter(new SessionEnforcerFilter());
        frb.setUrlPatterns(Arrays.asList(new String[]{"/*"}));
        return frb;
    }
    
    public class SessionEnforcerFilter implements Filter{
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {}
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
            HttpServletRequest httpServletRequest = (HttpServletRequest)request;
            HttpServletResponse httpServletResponse = (HttpServletResponse)response;
            if(httpServletRequest.getSession(false)==null){
                logger.debug("sessionEnforcerFilter.doFilter () - Session is null - forcing its creation");
                httpServletRequest.getSession();
                String requestURI = httpServletRequest.getRequestURI();
                logger.debug("sessionEnforcerFilter.doFilter () - Repeating request [{}]", requestURI);
                httpServletResponse.sendRedirect(requestURI);
            }else{
                chain.doFilter(httpServletRequest, response);
            }
        }
    
        @Override
        public void destroy() {}
    
    }
    

    摘要

  • 在SessionRepositoryResponseWrapper.onResponseCommitted()中保留断点

  • 检查SessionRepositoryRequestWrapper内的响应对象是否为非包装响应。(include=false)

  • 如果它是包装响应对象,请确保首先使用sessionRepositoryFilter

  • ================

    当“DispatcherType.INCLUDE(INCLUDE=true)”时,Spring会话已在处理该问题

    SessionRepositoryResponseWrapper.onResponseCommitted()正在尝试将Cookie添加到原始响应对象

    sessionRepositoryFilter必须位于第一个位置,才能包装tomcat传递的原始applicationHttpResponse

    问题情况

    • SessionRepositoryRequestWrapper接收包装好的响应并保存它

    • 在servlet容器中执行doInclude()时,找到原始响应并用ApplicationHttpResponse(include=true)包装它。 然后,将SetResponse(新包装响应)设置为最里面的包装

    • Spring会话对存储在SessionRepositoryResponseWrapper.onResponseCommitted()中的响应(应为原始响应)执行addCookie,但无法执行,因为它被设置为“included=true”

      • 摘要

      • 在SessionRepositoryResponseWrapper.onResponseCommitted()中保留断点

      • 检查SessionRepositoryRequestWrapper内的响应对象是否为非包装响应。(include=false)

      • 如果它是包装响应对象,请确保首先使用sessionRepositoryFilter

      • ================

        当“DispatcherType.INCLUDE(INCLUDE=true)”时,Spring会话已在处理该问题

        SessionRepositoryResponseWrapper.onResponseCommitted()正在尝试将Cookie添加到原始响应对象

        sessionRepositoryFilter必须位于第一个位置,才能包装tomcat传递的原始applicationHttpResponse

        问题情况

        • SessionRepositoryRequestWrapper接收包装好的响应并保存它

        • 在servlet容器中执行doInclude()时,找到原始响应并用ApplicationHttpResponse(include=true)包装它。 然后,将SetResponse(新包装响应)设置为最里面的包装

        • Spring会话对存储在SessionRepositoryResponseWrapper.onResponseCommitted()中的响应(应为原始响应)执行addCookie,但无法执行,因为它被设置为“included=true”