Ich sende eine $.getJSON
(HTTP GET) Anfrage zweimal (mit verschiedenen Daten), eine nach der anderen (sagen wir, wir haben Anfrage1 und Anfrage2). Ich kann in den Entwicklern von FF und Chrome sehen, dass ich das gleiche cookie:JSESSIONID=FD0D502635EEB67E3D36203E26CBB59A
Header-Feld habe.Warum wird getSession() nicht die gleiche Sitzung in nachfolgenden Anfragen in kurzen Zeiträumen distanziert zurückgegeben?
Auf der Serverseite Ich versuche, um die Sitzung zu bekommen:
HttpSession session = request.getSession();
boolean isSessionNew = session.isNew();
String sessionId = session.getId();
String cookieFromRequestHeader = request.getHeader("cookie");
Wenn ich diese Variablen für beide Anfragen drucke ich bekommen,
Anfrage1:
isSessionNew: true
cookieFromRequestHeader: JSESSIONID = FD0D502635EEB67E3D36203E26CBB59A
session.getId(): 9212B14094AB92D0F7F10EE21F593E52
request2:
isSessionNew: true
cookieFromRequestHeader: JSESSIONID = FD0D502635EEB67E3D36203E26CBB59A
session.getId(): E8734E413FA3D3FEBD4E38A7BF27BA58
Wie Sie sehen können, wird der Server eindeutig eine neue Sitzung erstellt für request2 auf einem request.getSession()
. Aber warum macht es das? Es sollte theoretisch synchronisiert werden und Ihnen die gleiche Sitzung geben, die die erste Anfrage (die diesen Code zuerst erreichte) erstellt hat. nun sicher sein, dass die Sitzung Schöpfung synchronisiert habe ich folgendes:
@Autowired
private ServletContext servletContext;
...
synchronized (servletContext) {
HttpSession session = request.getSession();
boolean isSessionNew = session.isNew();
String sessionId = session.getId();
String cookieFromRequestHeader = request.getHeader("cookie");
}
und ich habe die gleichen Ergebnisse.
Wenn ich die gleichen Anfragen später wieder senden (lässt Anfrage1' sagen und request2 ') ich werde,
Anfrage1':
isSessionNew: false
cookieFromRequestHeader: JSESSIONID = E8734E413FA3D3FEBD4E38A7BF27BA58 session.getId (): E8734E413FA3D3FEBD4E38A7BF27BA58
request2' :
isSessionNew: false
cookieFromRequestHeader: JSESSIONID = E8734E413FA3D3FEBD4E38A7BF27BA58
session.getId(): E8734E413FA3D3FEBD4E38A7BF27BA58
Wenn Sie genau jetzt sehen, ist die Session-ID die gleiche (in Anfrage1' und request2') und ist der Letzte, der aus der Anfrage erstellt wurde2. Gibt es eine Möglichkeit, die gleiche Sitzung von mehreren nachfolgenden Anfragen zu bekommen, die in sehr kurzen Zeiträumen zum Server kommen?
Ich verwende keine speziellen Funktionen - ich verwende die Out of the Box-Session-Strategie von Spring.Es sieht auch so aus, als käme der Cookie JSESSIONID aus den ersten 2 Anfragen (request1 und request2) vom ersten Mal, wenn ich die Seite besuche (sagen wir mal, es wurde eine Anfrage0 an den Server gesendet, als er diese JSESSIONID erstellt hat). Es sieht aber auch so aus, dass Sie, wenn Sie request.getSession() nicht explizit aufrufen, das Backend/Server immer eine neue JSESSIONID für jede Antwort erstellen und diese an den Client zurücksenden wird. Wenn also eine neue Anfrage von dem Client gesendet wird, nachdem eine Antwort kommt, wird sie eine neue JSESSIONID haben. Es sieht so aus, als ob die Spring Session-Behandlung nicht richtig funktioniert.
Mit freundlichen Grüßen,
Despot
ZUSÄTZLICHE RESEARCH:
Ich wollte sehen, ob ich die Session-Erstellung mit einem HttpSessionListner registrieren. Auf diese Weise kann ich sehen, wenn die Sitzung mit der ID FD0D502635EEB67E3D36203E26CBB59A (der Cookie, der in Anforderung1 und Anforderung2 gesendet wird) erstellt wird. Und auch, Wetter mit dem Listener (der SessionProcessor) Ich kann die Sitzungen in einer Karte nach ID speichern und später durch die ID aus dem Cookie abrufen (so muss ich keine weitere Sitzung erstellen).
So, hier ist der Code:
public interface ISessionProcessor extends ISessionRetriever, ISessionPopulator {
}
public interface ISessionRetriever {
HttpSession getSession(String sessionId);
}
public interface ISessionPopulator {
HttpSession setSession(String sessionId, HttpSession session);
}
Der Grund für die Trennung davon war, weil ich nur die Zuhörer erlauben wollte Sitzungen der Karte hinzuzufügen, und die Controller nur eine Sitzung über Anfrage erstellen zu können. getSession() - also wurde die Methode sessionCreated des Listners immer aufgerufen (wie Sie sehen werden).
public class SessionProcessor implements ISessionProcessor {
private Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();
@Override
public HttpSession getSession(String sessionId) {
return sessions.get(sessionId);
}
@Override
public HttpSession setSession(String sessionId, HttpSession session) {
return sessions.put(sessionId, session);
}
}
public class SessionRetrieverHttpSessionListener implements HttpSessionListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SessionRetrieverHttpSessionListener.class);
@Autowired
private ISessionPopulator sessionPopulator;
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
LOGGER.debug("Session with id {} created. MaxInactiveInterval: {} session:{}", new Object[]{session.getId(), session.getMaxInactiveInterval(), session});
sessionPopulator.setSession(session.getId(), session);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
// session has been invalidated and all session data (except Id) is no longer available
LOGGER.debug("Session with id {} destroyed. MaxInactiveInterval: {}, LastAccessedTime: {}, session:{}",
new Object[]{session.getId(), session.getMaxInactiveInterval(), session.getLastAccessedTime(), session});
}
}
in web.xml: org.springframework.web.context.ContextLoaderListener
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/my-servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<listener>
<listener-class>mypackage.listener.SessionRetrieverHttpSessionListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
in my-Servlet-context.xml:
<bean class="mypackage.listener.SessionProcessor"/>
<bean class="mypackage.SomeController"/>
in meinem Controller :
synchronized (servletContext) {
String cookieFromRequestHeader = request.getHeader("cookie");
LOG.debug("cookieFromRequestHeader:{}", new Object[] {cookieFromRequestHeader});
String jsessionIdFromCookieFromRequestHeader = cookieFromRequestHeader.substring(cookieFromRequestHeader.indexOf("=") + 1);
LOG.debug("jsessionIdFromCookieFromRequestHeader:{}", new Object[] {jsessionIdFromCookieFromRequestHeader});
session = sessionRetriever.getSession(jsessionIdFromCookieFromRequestHeader);
LOG.debug("session:{}", new Object[] {session});
if (session == null) {
LOG.debug("request.isRequestedSessionIdFromCookie():{}, request.isRequestedSessionIdFromURL():{}, WebUtils.getSessionId(request):{}.", new Object[] {request.isRequestedSessionIdFromCookie(), request.isRequestedSessionIdFromURL(), WebUtils.getSessionId(request)});
session = request.getSession();
boolean isSessionNew = session.isNew();
LOG.debug("Is session new? - {}. The session should not be new after the first fingerprint part is received - check if this occured in the logs - if that happend than there is an error!", isSessionNew);
LOG.debug("request.isRequestedSessionIdFromCookie():{}, request.isRequestedSessionIdFromURL():{}, WebUtils.getSessionId(request):{}.", new Object[] {request.isRequestedSessionIdFromCookie(), request.isRequestedSessionIdFromURL(), WebUtils.getSessionId(request)});
//read https://stackoverflow.com/a/2066883 and think about using ServletContextAware also.
LOG.debug("cookieFromRequestHeader:{} session.getId(): {}", new Object[]{cookieFromRequestHeader, session.getId()});
}
}
Dies gab mir die gleichen Ergebnisse. Es schien, dass die Sitzungserstellung mit anderen Mitteln als request.getSession (wenn Spring nicht in der Box die Sitzung erstellt hat) entweder vom Listener registriert wurde oder die cookie/jsessionID von woanders kam. Schauen Sie die Antwort für mehr an.
Andere Quellen, die mich durch die Http Fragen gehen geholfen:
servlet context injection in controller
overview of concurrency when you have to work with HttpSession
using HttpSession object to do synchronization (avoid this)
the "best" way to do synchronization when working with HttpSession
einige Frühjahr Referenz Zeug:
session management
session management in security
Diskussionen darüber, wie Sitzung zu bekommen wenn du eine sessionId hast (w Hut Ich habe oben):
coderanch discussion
stackoverflow
the post that helped me finalize my listener autowiring