2011-02-10 16 views

risposta

10

Il modo più semplice per farlo è utilizzare un filtro sugli URL delle richieste AJAX.

Nell'esempio che segue Sto solo l'invio di HTTP 500 codice di risposta con un corpo di risposta che indica il timeout di sessione, ma si può facilmente impostare il codice di risposta e il corpo a ciò che è più adatto per il vostro caso ..

package com.myapp.security.authentication; 

import org.springframework.web.filter.GenericFilterBean; 

import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 

public class ExpiredSessionFilter extends GenericFilterBean { 

    static final String FILTER_APPLIED = "__spring_security_expired_session_filter_applied"; 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 

     if (request.getAttribute(FILTER_APPLIED) != null) { 
      chain.doFilter(request, response); 
      return; 
     } 

     request.setAttribute(FILTER_APPLIED, Boolean.TRUE); 
     if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {    
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "SESSION_TIMED_OUT"); 
      return; 
     } 

     chain.doFilter(request, response); 
    } 
} 
+0

Dove posso aggiungerlo nel file di configurazione del bean? Ho provato prima e ho avuto problemi con esso. Non sono sicuro se l'ho configurato correttamente la prima volta. Questo sembra essere sulla strada giusta. –

+0

Supponendo che Spring Security sia configurato correttamente, è sufficiente aggiungere questo filtro alla catena dei filtri di sicurezza in applicationContext-security.xml: definire il filtro come _ _ e aggiungerlo alla catena utilizzando _ _ –

+0

Secondo te qual è il posto migliore per iniettare questo filtro con gli altri filtri. L'attributo del filtro personalizzato ha un prima/dopo che contiene filtri incorporati, http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#ns-custom-filters . Non voglio che venga eseguito su ogni pagina tramite ajax, ma solo su pagine protette come una sezione di amministrazione. Sicuramente l'ho colpito ora, devo solo assicurarmi che funzioni solo su quelle pagine sicure. Dopo di ciò hai ricevuto un controllo ANSWER da parte mia! –

3

Ecco un approccio che ritengo sia abbastanza semplice. È una combinazione di approcci che ho osservato su questo sito. Ho scritto un post sul blog: http://yoyar.com/blog/2012/06/dealing-with-the-spring-security-ajax-session-timeout-problem/

L'idea di base è utilizzare un prefisso api url (cioè/api/protetto) come suggerito sopra insieme a un punto di ingresso di autenticazione. È semplice e funziona.

Ecco il punto di ingresso di autenticazione:

package com.yoyar.yaya.config; 

import org.springframework.security.core.AuthenticationException; 
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; 

import javax.servlet.ServletException; 
import javax.servlet.http.*; 
import java.io.IOException; 

public class AjaxAwareAuthenticationEntryPoint 
      extends LoginUrlAuthenticationEntryPoint { 

    public AjaxAwareAuthenticationEntryPoint(String loginUrl) { 
     super(loginUrl); 
    } 

    @Override 
    public void commence(
     HttpServletRequest request, 
     HttpServletResponse response, 
     AuthenticationException authException) 
      throws IOException, ServletException { 

     boolean isAjax 
      = request.getRequestURI().startsWith("/api/secured"); 

     if (isAjax) { 
      response.sendError(403, "Forbidden"); 
     } else { 
      super.commence(request, response, authException); 
     } 
    } 
} 

Ed ecco ciò che accade nella vostra primavera contesto xml:

<bean id="authenticationEntryPoint" 
    class="com.yoyar.yaya.config.AjaxAwareAuthenticationEntryPoint"> 
    <constructor-arg name="loginUrl" value="/login"/> 
</bean> 

<security:http auto-config="true" 
    use-expressions="true" 
    entry-point-ref="authenticationEntryPoint"> 
    <security:intercept-url pattern="/api/secured/**" access="hasRole('ROLE_USER')"/> 
    <security:intercept-url pattern="/login" access="permitAll"/> 
    <security:intercept-url pattern="/logout" access="permitAll"/> 
    <security:intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/> 
    <security:intercept-url pattern="/" access="permitAll"/> 
    <security:form-login login-page="/login" 
         authentication-failure-url="/loginfailed" 
         default-target-url="/login/success"/> 
    <security:access-denied-handler error-page="/denied"/> 
    <security:logout invalidate-session="true" 
        logout-success-url="/logout/success" 
        logout-url="/logout"/> 
</security:http> 
1

utilizzare la stessa soluzione @ Matt in backend. Se stai utilizzando angularJs sul front-end, aggiungi l'interceptor sotto angolare $ http per consentire al browser di effettuare effettivamente un reindirizzamento alla pagina di accesso.

var HttpInterceptorModule = angular.module('httpInterceptor', []) 
.config(function ($httpProvider) { 
    $httpProvider.interceptors.push('myInterceptor'); 
    $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; 
}) 
.factory('myInterceptor', function ($q) { 
return { 
    'responseError': function(rejection) { 
     // do something on error 
     if(rejection.status == 403 || rejection.status == 401) window.location = "login"; 
     return $q.reject(rejection); 
    } 
    }; 

});

Nota che sotto la linea è necessaria solo se si sta utilizzando AngularJs dopo la versione 1.1.1 (angularJS rimossi intestazione "X-richiesta-Con" da quella versione in poi)

$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; 
1

Visto che tutti i le risposte attuali sono un paio di anni ormai, io condividere la mia soluzione, che ho attualmente lavorando in un'applicazione primavera avvio REST:

@Configuration 
@EnableWebSecurity 
public class UISecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     ... 
     http.exceptionHandling.authenticationEntryPoint(authenticationEntryPoint()); 
     ... 
    } 

    private AuthenticationEntryPoint authenticationEntryPoint() { 
     // As a REST service there is no 'authentication entry point' like MVC which can redirect to a login page 
     // Instead just reply with 401 - Unauthorized 
     return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); 
    } 
} 

la premessa fondamentale è che sovrascrivo il punto di ingresso di autenticazione che di default è stato rilasciare un reindirizzamento al mio login inesistente pag e. Ora risponde inviando un 401. Spring crea anche implicitamente un oggetto JSON di risposta agli errori standard che restituisce pure.

Problemi correlati