2016-05-25 20 views
6

Ho aggiunto questo codice in spring-security.xml per abilitare il controllo del timeout della sessione e il controllo della concorrenza.Come escludere alcune pagine dalla gestione delle sessioni (timeout/controllo della concorrenza) in Spring Security?

<sec:http> 
    <sec:form-login login-page="/login" login-processing-url="/authentication" 
        default-target-url="/home" always-use-default-target="true" 
        authentication-failure-url="/login?error=true" 
        username-parameter="userid" password-parameter="password"/> 
    <sec:logout logout-url="/logout" logout-success-url="/login" delete-cookies="JSESSIONID" invalidate-session="true" /> 

    <!-- User login (URL not View Name) --> 
    <sec:intercept-url pattern="/login" access="permitAll" /> 

    <!-- User change password --> 
    <sec:intercept-url pattern="/change_password" access="permitAll" /> 


    <sec:session-management invalid-session-url="/session_timeout"> 
     <sec:concurrency-control max-sessions="1" error-if-maximum-exceeded="false" expired-url="/session_conflict"/> 
    </sec:session-management> 

    <sec:headers> 
     <sec:frame-options policy="SAMEORIGIN" /> 
    </sec:headers> 
</sec:http> 

ma la domanda è,

  1. Ho bisogno di escludere qualche pagina come loginchange_password dal check della sessione (timeout e la concorrenza).

  2. Se si dispone di una pagina accessibile sia per utente registrato che per utente non registrato. Ma ho bisogno di fare timeout della sessione e la concorrenza verifica solo quando l'utente connesso.

Come dovrei implementare questo?

Grazie mille.

risposta

4

Aggiornamento: ho testato la mia risposta originale session="false" su una delle mie pagine di accesso di Spring Security e non ha funzionato. Vedi sotto per una soluzione migliore.


risposta originale:

Aggiungendo <% session @ page = "false" %> per la parte superiore del file JSP dovrebbe impedire una sessione venga avviato, ma questo non è correlata alla Primavera di sicurezza.

V'è una certa molto minimale documentazione di Oracle al seguente URL che dice:

JSP sessione predefinita Richieste

In generale, servlet non richiedere una sessione HTTP per impostazione predefinita. Tuttavia, le classi di implementazione della pagina JSP richiedono una sessione HTTP per impostazione predefinita. È possibile ignorare questo impostando il parametro di sessione su false in una direttiva pagina JSP, come segue:

<% @ page ... session =% "false"

https://docs.oracle.com/cd/A87860_01/doc/java.817/a83726/basics3.htm#1007356


Risposta aggiornata: il problema potrebbe essere correlato a Spring Security con CSRF abilitato. È abilitato di default nella versione 4.0, che è una buona cosa e non qualcosa che si desidera disabilitare. Nelle versioni precedenti potrebbe essere necessario essere manualmente.

I token CRSF richiedono una sessione, quindi è necessaria una soluzione per escludere il test CSRF solo durante il processo di accesso.

Si parla di "Relaxing CSRF" nel Riferimento di sicurezza di primavera. Menzionano specificamente SockJS ma il principio è universale.Essi suggeriscono qualcosa come la linea di seguito per JavaConfig:

http.csrf().ignoringAntMatchers("/login") 

La accettato answer by P.Peter for the SO question "CSRF token expires during login" ha una soluzione simile che richiede un piccolo sforzo in più.

È necessario aggiungere una classe che implementerà classe RequestMatcher di primavera e sovrascrivere esso è corrispondenze() metodo:

class CsrfSecurityRequestMatcher implements RequestMatcher { 
    @Override 
    public boolean matches(HttpServletRequest request) { 
     return !request.getServletPath().equals("/login"); 
    } 
} 

Se avete bisogno di logica corrispondenza più complessa è possibile aggiungere Pattern e campi RegexRequestMatcher nella tua classe RequestMatcher personalizzato e usali nel tuo metodo matches().

Quindi sarà necessario aggiungere un riferimento alla nuova classe nella configurazione di Spring Security. In XML sarebbe qualcosa di simile:

<http> 
    <csrf request-matcher-ref="csrfSecurityRequestMatcher"/> 
</http> 

In JavaConfig sarebbe qualcosa di simile:

http.csrf().requireCsrfProtectionMatcher(new CsrfSecurityRequestMatcher()); 

io sono sicuro che cosa ramificazioni di sicurezza ci possono essere alla disattivazione di test CSRF sulla pagina di login quindi potresti volerlo esaminare.

Se si decide che disabilitare CSRF per la propria pagina di accesso non è accettabile, è possibile utilizzare una soluzione keepalive AJAX che impedisce la scadenza della pagina di accesso ma che è un po 'trucchetto per i miei gusti.

3

La sessione viene creata indipendentemente dalla molla, dalla sicurezza, ecc. Il meccanismo dietro la sessione è completamente automatico, non è necessario cambiare o fare nulla. Invece di scavare nei dettagli di Spring, puoi utilizzare l'API javax.servlet e ottenere ciò di cui hai bisogno.

E ciò che è necessario fare è semplice: distinguere tra sessione anonima e sessioni utente autenticate con l'aiuto di oggetto personalizzato associato alla sessione.

La sessione può contenere oggetti e il server mantiene gli oggetti associati a una sessione specifica (normalmente tramite il cookie di sessione jsessionid). Esempio di un tale oggetto è seguente codice:

public class SessionUsr implements java.io.Serializable { 
    private static final long serialVersionUID = 6034793247940424913L; 

    // do not make this fields nonfinal. This object is in session as serialized stream and 
    // setting the fields does not refresh the object in session. You must replace it 

    protected final boolean isAnonymous; 
    protected final String userName; 

    public SessionUsr(boolean isAnonymous, String userName) { 
     super(); 
     this.isAnonymous = isAnonymous; 
     this.userName = userName; 
    } 
    public boolean isAnonymous() { 
     return this.isAnonymous; 
    } 
    public String getUserName() { 
     return this.userName; 
    } 

    @Override 
    public String toString() { 
     return "SessionUsr [isAnonymous=" + this.isAnonymous + ", userName=" + this.userName + "]"; 
    } 
    @Override 
    public int hashCode() { 
     int result = 17; 
     result = 31 * result + (null == getUserName() ? 0 : getUserName().hashCode()); 
     result = 31 * result + (!isAnonymous() ? 0 : 1); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (!(obj instanceof SessionUsr)) { 
      return false; 
     } 

     final SessionUsr comparation= (SessionUsr) obj; 
     if (comparation.getUserName().equals(this.userName)) 
      return true; 

     return false; 
    } 

} 

ascoltatore sessione per tenere traccia degli eventi

import java.util.logging.Logger; 
import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 

public class SessionListener implements HttpSessionListener { 

    public static final Logger log = Logger.getLogger(SessionListener.class.getCanonicalName()); 

    /** 
    * Method is called after new client connects 
    * @see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent) 
    */ 
    @Override 
    public void sessionCreated(HttpSessionEvent arg0) { 
     log.info("SESSION CREATED with id " + arg0.getSession().getId()); 
     final SessionUsr authenticatedUser = new SessionUsr(false, "anonymous"); 
     arg0.getSession().setAttribute("_USR", authenticatedUser); 
    } 

    /** 
    * Invalidation or timeout definined in web.xml (session-timeout). 
    * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent) 
    */ 
    @Override 
    public void sessionDestroyed(HttpSessionEvent arg0) { 
     log.info("SESSION DESTROYED, INVALIDATED " + arg0.getSession().getId()); 
    } 

} 

Nel codice di autorizzazione e autenticazione, dopo che l'utente viene convalidato correttamente, si sostituisce l'attributo sessione con il codice

final SessionUsr authorizated = new SessionUsr("John Kennedy", true); 
getSession().setAttribute("_USR", authorizated); 

E si può recuperare questo utente ovunque con:

final SessionUsr authenticatedUser = (SessionUsr) getSession().getAttribute("_USR"); 
Problemi correlati