2012-10-22 25 views
13

मैं $.getJSON (HTTP GET) अनुरोध दो बार (अलग-अलग डेटा के साथ) अनुरोध कर रहा हूं, एक के बाद एक (मान लें कि हमारे पास request1 और request2 है)। मैं एफएफ और क्रोम से डेवलपर टूल्स में देख सकता हूं कि मेरे पास cookie:JSESSIONID=FD0D502635EEB67E3D36203E26CBB59A हेडर फ़ील्ड है।क्यों नहीं मिलता है सत्र() कम समय अवधि में दूर किए गए अनुरोधों में उसी सत्र को वापस कर रहा है?

सर्वर साइड मैं सत्र प्राप्त करने की कोशिश में:

HttpSession session = request.getSession(); 
boolean isSessionNew = session.isNew(); 
String sessionId = session.getId(); 
String cookieFromRequestHeader = request.getHeader("cookie"); 

अगर मैं दोनों अनुरोधों मैं के लिए इन चरों प्रिंट,
request1:

isSessionNew: सच
cookieFromRequestHeader: JSESSIONID = FD0D502635EEB67E3D36203E26CBB59A
session.getId(): 9212B14094AB92D0F7F10EE21F593E52

request2:

isSessionNew: सच
cookieFromRequestHeader: jsessionid = FD0D502635EEB67E3D36203E26CBB59A
session.getId(): E8734E413FA3D3FEBD4E38A7BF27BA58

आप देख सकते हैं, सर्वर स्पष्ट रूप से बनाए गए एक नए सत्र request.getSession() पर request2 के लिए। लेकिन यह ऐसा क्यों करता है? इसे सैद्धांतिक रूप से सिंक्रनाइज़ किया जाना चाहिए और आपको वही सत्र देना चाहिए जो पहला अनुरोध (जो पहले इस कोड पर पहुंचा) बनाया गया था। अब, यह सुनिश्चित करें कि सत्र सृजन सिंक्रनाइज़ है मैं निम्नलिखित किया जा करने के लिए:

@Autowired 
private ServletContext servletContext; 
... 
synchronized (servletContext) { 
    HttpSession session = request.getSession(); 
    boolean isSessionNew = session.isNew(); 
    String sessionId = session.getId(); 
    String cookieFromRequestHeader = request.getHeader("cookie"); 
} 

और मैं एक ही परिणाम मिला है।

अगर मैं बाद में फिर से एक ही अनुरोध भेजने (देता है request1 'और request2' कहते हैं) मैं मिलता है,
request1 ':

isSessionNew: झूठी
cookieFromRequestHeader: jsessionid = E8734E413FA3D3FEBD4E38A7BF27BA58 session.getId (): E8734E413FA3D3FEBD4E38A7BF27BA58

request2 ':

isSessionNew: झूठी
cookieFromRequestHeader: jsessionid = E8734E413FA3D3FEBD4E38A7BF27BA58
session.getId(): E8734E413FA3D3FEBD4E38A7BF27BA58

तुम करीब से अब देखते हैं, तो सत्र id ही (request1 में 'और request2') और है अनुरोध 2 से बनाया गया अंतिम। क्या मुझे बहुत ही कम समय के अनुरोधों में सर्वर पर आने वाले कई बाद के अनुरोधों से एक ही सत्र प्राप्त करने का कोई तरीका है?

मैं किसी विशेष विशेषताओं का उपयोग नहीं कर रहा हूं - मैं बॉक्स सत्र रणनीति के बाहर स्प्रिंग का उपयोग कर रहा हूं।साथ ही, यह फ्रिस्ट 2 अनुरोध (अनुरोध 1 और अनुरोध 2) से कुकी JSESSIONID की तरह दिखता है जब मैं पृष्ठ पर पहली बार जाता हूं (मान लें कि सर्वर पर यह अनुरोध भेजा गया था जब यह JSESSIONID बनाया गया था)। लेकिन यह तब भी दिखता है जब तक कि आप स्पष्ट रूप से request.getSession() को कॉल नहीं करते हैं, बैकएंड/सर्वर हमेशा प्रत्येक प्रतिक्रिया के लिए एक नया JSESSIONID बना देगा और उसे क्लाइंट को वापस भेज देगा। तो जब प्रतिक्रिया के बाद ग्राहक से नया अनुरोध भेजा जाता है, तो उसके पास एक नया JSESSIONID होगा। ऐसा लगता है कि बॉक्स सत्र हैंडलिंग से बाहर वसंत उचित रूप से काम नहीं कर रहा है।

सधन्यवाद,
तानाशाह

अतिरिक्त अनुसंधान:

मैं अगर मैं एक HttpSessionListner साथ सत्र निर्माण रजिस्टर कर सकते हैं देखना चाहती थी। इस तरह मैं देख सकता हूं कि आईडी FD0D502635EEB67E3D36203E26CBB59A वाला सत्र (अनुरोध 1 और अनुरोध 2 में भेजा जा रहा कुकी) बनाया गया है। और, श्रोता (सत्रप्रोसेसर) का उपयोग करने का मौसम मैं आईडी द्वारा मानचित्र में सत्रों को स्टोर कर सकता हूं और बाद में उन्हें कुकी से आईडी द्वारा पुनर्प्राप्त कर सकता हूं (इसलिए मुझे एक और सत्र बनाने की आवश्यकता नहीं है)।

public interface ISessionProcessor extends ISessionRetriever, ISessionPopulator { 
} 

public interface ISessionRetriever { 

    HttpSession getSession(String sessionId); 
} 

public interface ISessionPopulator { 

    HttpSession setSession(String sessionId, HttpSession session); 
} 

अलग इन था, क्योंकि मैं केवल श्रोता नक्शा करने के लिए सत्र को जोड़ने की अनुमति चाहते थे, और नियंत्रकों केवल अनुरोध के माध्यम से एक सत्र बनाने के लिए सक्षम होना करने के लिए कारण:
तो यहाँ कोड है। getSession() - तो श्रोता का सत्र हमेशा तैयार की गई विधि को लागू किया गया था (जैसा कि आप नीचे देखेंगे)।

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}); 
    } 
} 
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> 
मेरी-सर्वलेट-context.xml में

:

<bean class="mypackage.listener.SessionProcessor"/> 
<bean class="mypackage.SomeController"/> 
मेरी नियंत्रक में

:

    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()}); 
          } 
        } 

इससे मुझे एक ही परिणाम मिला। ऐसा प्रतीत होता है कि अनुरोध के अलावा अन्य तरीकों से सत्र निर्माण .getSession (जब वसंत स्वयं बॉक्स से बाहर वसंत करता है), या तो श्रोता द्वारा पंजीकृत नहीं किया गया था या कुकी/jsessionID कहीं और से आया था। अधिक के लिए उत्तर देखें।

अन्य सूत्रों कि मुझे HttpSession मुद्दों के माध्यम से जाने में मदद की:
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
कुछ वसंत संदर्भ सामान: कैसे सत्र पाने के लिए पर
session management
session management in security
विचार विमर्श जब आपके पास सत्र आईडी (डब्ल्यू टोपी मैंने ऊपर किया था):
coderanch discussion
stackoverflow
the post that helped me finalize my listener autowiring

उत्तर

1

यह frist 2 अनुरोध (request1 और request2 से कुकी jsessionid तरह दिखता है) पहली बार मैं पेज जाएँ से आते हैं (की सुविधा देता है कहें कि सर्वर पर भेजा गया एक अनुरोध 0 था जब यह JSESSIONID बनाया गया था)।

यह सच नहीं था। मेरे पास एक ही डोमेन पर उसी डोमेन पर दो अनुप्रयोग तैनात हैं। तो जब मैं http://mydomain.com/app1/initpage पर फोन कर रहा था, तो सर्वर ने आईडी FD0D502635EEB67E3D36203E26CBB59A के साथ ऐप 1 के लिए सत्र बनाया और क्लाइंट को कुकी में यह JSESSIONID भेजा। क्लाइंट ने mydomain.com के तहत कुकी को सहेज लिया और दूसरी बार जब मैंने http://mydomain.com/app2/executeService निष्पादित किया, क्लाइंट ब्राउजर ने अनुरोध हेडर में कुकी से JSESSIONID भेजा। मैंने इसे सर्वर पर प्राप्त किया लेकिन यह अन्य ऐप 2 में एक सत्र नहीं था।

यह तथ्य बताता है कि जब मैं अन्य दो अनुरोध (request1 'और request2') भेजता हूं तो उनके पास उचित आवेदन पर सत्र सत्र बनाया गया है।
Deploying multiple web apps in same server
Under what conditions is a JSESSIONID created?

मेरे सवाल, ऐसा लगता है कि आप 1 अनुरोध इतना सिंक्रनाइज़ आप हमेशा सुनिश्चित करें कि आप होती है बनाने की जरूरत है के लिए ठोस जवाब के लिए के रूप में:

एक नज़र अधिक यहाँ है निम्नलिखित अनुरोधों में एक ही सत्र आईडी। पहले के बाद निम्नलिखित अनुरोध, हालांकि असीमित हो सकते हैं।

0

क्लाइंट में अपनी कुकी (JESSIONID के साथ) को स्टोर करें, जब आप सर्वर को बाद में अनुरोध भेजें, संग्रहीत कुकी को अपने अनुरोध हेडर फ़ील्ड में रखें और भेजें, तो आपको सर्वर के अंत में एक ही सत्र मिल जाएगा।

// Put the stored cookie in your request header 
[(NSMutableURLRequest*)request addValue: DATA.cookies forHTTPHeaderField:@"cookie"]; 
[NSURLConnection sendAsynchronousRequest: request queue:[NSOperationQueue mainQueue] completionHandler:nil]; 

इतना ही आईओएस के लिए ग्राहक:

ग्राहक (आईओएस) अपने कुकी प्रतिक्रिया से की दुकान:

NSHTTPURLResponse* httpURLReqponse = (NSHTTPURLResponse*) response; 
    NSDictionary* allHeaders = [httpURLReqponse allHeaderFields]; 
    NSLog(@"Response Headers : %@ ", allHeaders); 
    NSString* cookie = [allHeaders objectForKey: @"Set-Cookie"]; 
    DATA.cookies = cookie;  // Store the cookie 

ग्राहक (आईओएस) कुकी के साथ अपने बाद के अनुरोध भेजें।

सर्वर (JavaEE) प्राप्त HttpSession:

// Get the session, print its hashCode. You will find out that it's same as previous. 
HttpSession session = ServletActionContext.getRequest().getSession(); 
0

मैंने देखा कि यह होता है कि जब कुकीज़ ...web.xml फ़ाइल में अक्षम हैं:

फिर, सर्वर अंत में, आप एक ही सत्र मिल जाएगा
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd"> 
<glassfish-web-app error-url=""> 

    <context-root>/some-app</context-root> 

    <class-loader delegate="true"/> 

    <jsp-config> 
     <property name="keepgenerated" value="true"> 
      <description>Keep a copy of the generated servlet class' java code.</description> 
     </property> 
    </jsp-config> 

    <session-config> 
     <session-properties> 
      <property name="timeoutSeconds" value="600"/> 
      <property name="enableCookies" value="false"/> 
     </session-properties> 
    </session-config> 

</glassfish-web-app> 

यह उसी कनेक्शन से सत्र आईडी को बनाए रखने के लिए <property name="enableCookies" value="false"/> होना चाहिए।