2016-07-14 4 views
1

Ich verwende Spring Session 1.2.0.RELEASE auf einem Spring Boot-Projekt. Dies ist als ein Krieg verpackt und auf Tomcat 8 bereitgestellt.Spring Session funktioniert nicht auf Tomcat 8 bei Verwendung von Tiles - SESSION Cookie ist nicht gesetzt, da die Antwort bereits enthalten ist

Ich habe Spring Session-Dokumentation gefolgt und konfiguriert es richtig. Das Problem besteht darin, dass der Einstiegspunkt für die Anwendung ein Controller ist, der einen Wert für die Sitzung festlegt, der SESSION-Cookie jedoch nicht an den Browser gesendet wird.

Debuggen Ich sehe, dass:

  1. org.springframework.session.web.http.CookieHttpSessionStrategy.onNewSession() versucht das Cookie zu schreiben:

    this.cookieSerializer .writeCookieValue(new CookieValue(request, response, cookieValue));

  2. org.springframework.session.web.http.DefaultCookieSerializer.writeCookieValue() setzt das Cookie in der Antwort:

    response.addCookie(sessionCookie);

  3. Der Cookie ist nicht wirklich geschrieben. Das zugrunde liegende Antwortobjekt ist org.apache.catalina.core.ApplicationHttpResponse. Seine addCookie() Methode ist:

    /** 
        * 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); 
    
    } 
    

Das Problem ist, dass included Attribut, das an einem gewissen Punkt wahr gesetzt ist, von der das Cookie zu verhindern hinzugefügt wird.

Dies geschieht, wenn die JSP (Fliese verwendet wird) bedient wird:

enter image description here

UPDATE:

Dies ist der Moment, wenn die Antwort als eingeschlossene Marke gesetzt wird (bei Standard. Jsp Kachellayout fügt ein Attribut ein:

<tiles:insertAttribute name="header" ignore="false"/>

enter image description here

Antwort

0

Um dieses Problem zu umgehen, habe ich einen Filter erstellt, um die Erstellung der Sitzung zu erzwingen.

Wie gesehen, hat der erste Aufruf des Controllers den Cookie nicht hinzugefügt, da die Antwort beim Tiles-JSP-Rendering bereits als eingeschlossen markiert war. Was ich tue, erzwingt die Erstellung der Sitzung im Filter und Umleitung fragt die gleiche AnfrageURI. Da der Aufruf kein Tiles-Rendering beinhaltet, wird der Cookie erstellt und kann sofort in den nächsten Aufrufen verwendet werden.

@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() {} 

} 
0

Zusammenfassung

  1. Hold-Haltepunkt in SessionRepositoryResponseWrapper.onResponseCommitted().

  2. Überprüfen Sie, ob das Antwortobjekt innerhalb des SessionRepositoryRequestWrapper eine nicht umbrochene Antwort ist.(included = false)

  3. Wenn es sich um ein eingepacktes Antwortobjekt handelt, stellen Sie sicher, dass der sessionRepositoryFilter an erster Stelle steht.

================

Frühlings-Session ist der Umgang mit bereits das Problem, wenn 'DispatcherType.INCLUDE (inbegriffen = true)'.

SessionRepositoryResponseWrapper.onResponseCommitted() versucht ,Cookie zum ursprünglichen Antwortobjekt hinzuzufügen.

Der SessionRepositoryFilter muss an der ersten Position sein, um die ursprüngliche Anwendung HttpResponse, die von Tomcat übergeben wurde, zu umbrechen.

Problem Situation

  • Die SessionRepositoryRequestWrapper empfängt die verpackte Reaktion und hält sie.

  • Wenn Sie doInclude() im Servlet-Container ausführen, suchen Sie die ursprüngliche Antwort und wickeln Sie sie mit ApplicationHttpResponse (included = true). Dann SetResponse (neue Wrapping-Antwort) zum innersten Wrapper.

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat.embed/tomcat-embed-core/8.0.24/org/apache/catalina/core/ApplicationDispatcher.java#ApplicationDispatcher.doInclude%28javax.servlet.ServletRequest%2Cjavax.servlet.ServletResponse%29

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat.embed/tomcat-embed-core/8.0.24/org/apache/catalina/core/ApplicationDispatcher.java#ApplicationDispatcher.wrapResponse%28org.apache.catalina.core.ApplicationDispatcher.State%29

  • Frühlings-Sitzung hat eine addCookie auf die Antwort (die ursprüngliche Antwort erwartet) in SessionRepositoryResponseWrapper.onResponseCommitted gespeichert(), aber es kann nicht, weil es gesetzt zu "enthalten = wahr".
Verwandte Themen