2012-07-05 15 views
14

Więc skończę z tym ...JsessionId - jak uniknąć; jsessionid = XXX przy pierwszym wywołaniu strony? to działa, czy pierwsza strona jest JSP

Mam aplikacja, która wykorzystuje się index.jsp welcome-strony z <iframe></iframe> zawartości iframe jest JSF strona. Gdybym dostęp index.jsp widzę cookie już na pierwszym Wsiadaj Firebug:

Set-Cookie JSESSIONID=C615DA89B6EF73F801973EA3DCD3B226; Path=/ 

strony z dziedziczy ten JSESSIONID. ALE: kiedy mam bezpośredni dostęp do strony z <iframe/>, otrzymuję jsessionId przepisany na wszystkie adresy URL bez pliku cookie - na pierwsze żądanie. Następnie używany jest plik cookie. Wszystko jest w porządku - jeśli: System zabezpieczeń pozwoliłby mi na przepisywanie adresów URL.

uruchomić JBoss 4.2.2

chcę osiągnąć takie samo zachowanie jak mam z index.jsp - przykład zawsze używaj ciasteczek i zawsze unikaj przepisywania http.

[EDIT] dzięki odpowiedzi balusc za to pisałem:

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

Nie zapomnij dodać go do listy 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> 

Odpowiedz

12

Od Servlet 3.0 można użyć <tracking-mode>COOKIE</tracking-mode> dla to. Ale ponieważ JBoss 4.2.2 nie jest kompilatorem Servlet 3.0, nie jest to możliwe.

Najprościej byłoby utworzyć filtr serwletów, który wysyła przekierowanie do HttpServletRequest#getRequestURI(), gdy HttpSession#isNew() zwraca true. Nie zapomnij sprawdzić HttpServletRequest#isRequestedSessionIdFromCookie(), aby zapobiec nieskończonej pętli przekierowania, gdy klient w ogóle nie obsługuje plików cookie.

+1

dzięki. Czy gdzieś na twojej stronie jest "darowizna na dobroć"? Czy mogę zamówić pizzę? – Toskan

+0

Nie ma za co. W prawej kolumnie mojej witryny/blogu znajduje się przycisk wpłaty w systemie PayPal. To jedyna droga do tej pory. – BalusC

+0

wygląda na to, że nie mogę wysłać Ci osobistej wiadomości. Powinieneś wymyślić, jak wymusić na paypal angielski. Ten holender jest nieco mylący :-) "Snel doneren" :-D – Toskan

2

Można to zrobić za pomocą prostego filtru, który zawija żądanie za pomocą HttpServletRequest, który przesłania HttpServletRequest.encodeURL i HttpServletRequest.encodeRedirectURL. Po prostu zwróć argument String przekazany do niego, a wyłączysz ponowne pisanie adresu URL. Pamiętaj, że działa to tylko dla pojedynczej aplikacji internetowej, chyba że chcesz ją skonfigurować w wersji conf/web.xml (niezalecane) lub skonfigurować ją we wszystkich oddzielnych aplikacjach internetowych.

Ta technika jest lepsza od tej opublikowanej później w pytaniu, ponieważ nie wymaga przekierowania, które może spowolnić Twoje żądania. IMO, jest także czystszy.

+0

Muszę to sprawdzić jak najszybciej. Co masz na myśli mówiąc o "pojedynczej" aplikacji internetowej? Nie jestem do końca pewien, co masz na myśli. – Toskan

+0

Filtry są skonfigurowane w 'WEB-INF/web.xml', które będą chronić tylko jedną aplikację webapp zgodnie z opisem. –

+0

powodem, dla którego akceptuję odpowiedź balusc, jest to, co zaimplementowałem i dobrze pasuje do opisanego problemu - nie mam czasu wypróbowywać twojego rozwiązania, ale brzmi dobrze – Toskan

3

Na podstawie rekomendacji Christophera Schultza spróbowałem tego i działa.

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 { 
     } 
    } 

i następującego wpisu w 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> 

Działa świetnie !!!.

+0

Jeśli pliki cookie są wyłączone, lepiej sprawdź kod i podaj ostrzeżenie. Założeniem jest, że plik cookie jest włączony po stronie klienta. – Reddymails

Powiązane problemy