2013-05-12 15 views
16

Qual è il modo preferito di creare pattern nell'elemento intercept-url in Spring security? Sto creando un servizio Web (RESTful) e al momento richiedo che tutti gli utenti abbiano effettuato l'accesso e abbiano il ruolo ROLE_USER. Quindi ulteriori vincoli vengono applicati dalle annotazioni @PreAuthorize sul livello di servizio. Tuttavia è comune aggiungere anche più elementi intercept-url con configurazione diversa?Utilizzo di intercept-url in Spring security

risposta

3

La configurazione del SpringSecurity dipende dalla autenticazione selezionato per la vostra applicazione: Ad esempio, per l'autenticazione form che si desidera configurare l'URL di login e logout successo URL senza permesso:

<http realm="Contacts Realm"> 
    <intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    <intercept-url pattern="/**" access="ROLE_USER"/> 
    <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/> 
    <logout logout-success-url="/index.jsp"/> 
</http> 

In caso di l'autenticazione di base non avete il login e logout degli URL e la configurazione è semplice:

<http realm="Contacts Realm"> 
    <intercept-url pattern="/**" access="ROLE_USER"/> 
    <http-basic/> 
</http> 

Nel caso in cui si seleziona usa autenticazione di base il secondo esempio.

+1

E ... questo non risponde molto più di quanto ho già scritto nella domanda. Esegui il resto dell'autorizzazione nel livello di servizio, quindi? (è un servizio web REST, utilizzando BASIC) – LuckyLuke

0

Spring Security è generalmente utile per l'accesso basato sul ruolo. e questo è tutto. È possibile creare il proprio ProcessingFilter per fare alcune cose aggiuntive. Tuttavia, trovo che questo è un sacco di lavoro per il piccolo benifit.

L'alternativa consiste nell'utilizzare gli Interceptor di richiesta. Su diversi progetti per servizi RESTful che utilizzano Spring MVC, utilizzo Request Interceptors per finalizzare alcune autenticazioni oltre l'accesso di base al ruolo. Questo funziona e, secondo me, rende la catena di eventi molto più facile da seguire, ma se hai a che fare con migliaia di transazioni al minuto, potrebbe impantanare le richieste.

2

L'intercettazione degli URL può essere eseguita in questo modo. Supponiamo che gli URL del servizio di riposo inizino con /rest/.

<http auto-config="true" use-expressions="true" access-denied-page="/accessDeniedPageURL"> 
    <intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')"/> 
    <intercept-url pattern="/view/products" access="isFullyAuthenticated()"/>   

    <form-login login-page="/landing" default-target-url="/view/products" authentication-failure-handler-ref="authenticationFailureHandler"/> 
    <logout invalidate-session="true" logout-success-url="/landing" delete-cookies="JSESSIONID"/> 

    <session-management invalid-session-url="/landing" session-authentication-error-url="/landing?msg=alreadyLogin"> 
     <concurrency-control max-sessions="1" expired-url="/landing?msg=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/> 
    </session-management>  
</http> 
7

La maggior parte delle applicazioni web utilizzando Primavera di sicurezza hanno solo un paio di intercept-url s perché hanno solo requisiti di sicurezza basilari. È necessario disporre dell'accesso non autenticato alle schermate di accesso e di errore di accesso e di solito ad alcuni aspetti del sito pubblico, in modo che possano essere presenti alcuni pattern URL. Poi c'è spesso una sezione di amministrazione, e poi tutto il resto è ROLE_USER.

Se sono necessari più ruoli, è consuetudine associarli ai componenti del percorso URL di livello superiore. Sebbene non sia richiesto, rende più facile assicurarsi che le risorse siano adeguatamente protette.

<http realm="Contacts Realm" use-expressions="false"> 
    <intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    <intercept-url pattern="/admin/*" access="ROLE_ADMIN"/> 
    <intercept-url pattern="/secret/*" access="ROLE_SECRET"/> 
    <intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN,ROLE_SECRET"/> 
    <http-basic/> 
</http> 

È necessario decidere, in base ai casi d'uso, se si desidera consentire alle persone di avere più ruoli. È più difficile da gestire nell'app, quindi la maggior parte delle persone con una sicurezza semplice lo ha configurato in modo che gli utenti abbiano esattamente un ruolo e quindi consentano più ruoli per accedere al contenuto protetto. L'altro modo per farlo, ovviamente, è un ruolo per pattern URL e dare alle persone più ruoli.

In ogni caso, la risposta alla tua domanda (o almeno alla domanda penso che ti stai chiedendo) è che la solita cosa da fare è una componente del percorso di alto livello per ruolo proteggendo tutte le risorse con le stesse restrizioni di sicurezza. Naturalmente, stai anche raggruppando le funzionalità sotto quel prefisso del percorso, quindi alcune persone odiano questa struttura e alcune persone preferiscono semplicemente usare le annotazioni nel codice. Mi piace la mia sicurezza, in cui posso vederlo in un unico posto e posso facilmente dire quali sono le aspettative di sicurezza osservando l'URL.

+0

Questo è sbagliato: access = "ROLE_ADMIN", dovrebbe essere "hasRole ('ROLE_ADMIN')" – otterslide

+0

@otterslide Spring introdotto [controllo di accesso basato sull'espressione] (http: // docs .spring.io/spring-security/site/docs/3.0.x/reference/el-access.html) come opzione, ma non un requisito. Per usarlo è necessario impostare l'attributo 'use-expressions' del tag' http' su 'true', che in questo esempio non si vede. Il controllo degli accessi basato su espressioni consente restrizioni più complicate rispetto alle semplici restrizioni basate sui ruoli illustrate qui, ma non è altrimenti migliore. Poiché gli errori di configurazione sono una fonte importante di errori di sicurezza, preferisco la semplice configurazione basata sui ruoli, laddove possibile. –

+0

Questo ha senso, ma sto usando Spring 4 e 'use-expressions' è impostato su 'true'. Vedi http://www.springframework.org/schema/security/spring-security.xsd, dice che il valore predefinito è true. Vedo le precedenti impostazioni predefinite di Spring 3 come false. Potrebbe essere utile menzionare use-expressions = "false" potrebbe essere richiesto nella risposta. L'ho provato, senza use-expressions = "true", e non ha funzionato, funzionano solo le espressioni. Grazie. – otterslide

17

dovrei pensare che "il modo migliore" è [necessariamente] soggettiva. Ho avuto <intercept-url> elementi a mio security.xml, ma li ha abbandonati a favore di @RequestMapping annotazioni con @PreAuthorize sui controller. È una preferenza puramente personale (nel mio caso), poiché preferisco mantenere le cose in Java piuttosto che nei namespace XML, per quanto sia possibile farlo.

È possibile utilizzare uno, l'altro o entrambi, ed è possibile effettuare l'annotazione migliorare l'XML - è possibile, ad esempio, avere qualcosa di simile al seguente:

security.xml:

<intercept-url pattern="/something" access="hasRole('ROLE_USER')"/> 

YourController.java:

@RequestMapping(value="/something/else") 
@PreAuthorize("hasRole('ROLE_ADMIN')") 
public String getSomethingElseContents(){ return "somethingelse"; } 

come ho detto, sembra che è solo una questione di preferenza. Il vantaggio di utilizzare lo spazio dei nomi XML è che le regole di accesso di base sono tutte in un unico posto, facili da leggere e facili da seguire. Le regole imposte da @PreAuthorize (o le altre varianti di annotazione) sono particolarmente sexy, perché è possibile chiamare il proprio espressione SPEL in loro, e basare la decisione autorizzazione per l'accesso ai parametri passati o campi accessibili dalla classe (cioè @PreAuthorize("@my.project.package.hasMagicPower(#power.INVISIBILITY)")), o combinazioni di queste. È possibile applicare autorizzazioni logiche e dinamiche che altrimenti non sono disponibili per l'opzione namespace.

Naturalmente si può applicare la logica rudimentale con la 'e', ​​'o' e '!' connettivi nelle espressioni Spel nello spazio dei nomi (e potresti essere in grado di accedere ai metodi di classe esterna [booleana] tramite il designatore @ nell'XML), ma tutto ciò che è specificato nell'XML deve essere statico.


tl; dr: preferenza personale è la preferenza, ma se si vuole o bisogno di flessibilità dinamica nella vostra gestione autorizzazione, è avere usare le annotazioni. Se non vuoi né hai bisogno di flessibilità dinamica, hai l'opzione (e un argomento valido suggerirebbe che l'opzione namespace è migliore rispetto a SoC). Preferisco lasciare che sia Java a gestirlo per la flessibilità e perché una volta impostato il mio XML, voglio lasciarlo da solo e concentrarmi su Java. Inoltre, c'è un controsenso alquanto convincente per la vista SoC, ovvero che un'applicazione Java correttamente convenzionale avrà i suoi controller in pacchetti facili da trovare con controllo ovvio per nome.


ancora tl; dr: Meh. Sei di una, mezza dozzina di altre. Dico po-tay-to.

1

Sì, è abbastanza comune per definire più modelli intercetta-url e quindi aggiungere annotazioni sulla parte superiore per limitare ulteriormente le risorse particolari.

È anche possibile utilizzare una directory per ciascun punto di restringimento in modo che modo non sarà necessario annotazioni. Ex./user/** richiede ROLE_USER,/admin/** richiede ROLE_ADMIN, ecc.

Ricordare quando si utilizza uno dei due metodi su come influisce sulla sicurezza in caso di errore.

Se si utilizza intercetta URL, è necessario mettere le linee nell'ordine corretto, per esempio:

<intercept-url pattern="/**" access="permitAll"/> 
<intercept-url pattern="/user/**" access="hasRole('ROLE_USER')"/> 

Non funzionerà, perché si sta grata tutti gli accessi in prima linea, in modo che le linee devono essere invertito. Se un principiante sta lavorando al tuo progetto e inverte le linee, potrebbe essere un grosso problema.

Se si utilizzano annotazioni, è possibile eliminare la riga di annotazione per errore, lasciando un buco di sicurezza nell'applicazione.

@PreAuthorize("hasRole('ROLE_USER')") 

Se si sono ri-utilizzando una classe controller tra i due progetti, e in un progetto che si desidera consentire ROLE_USER a tutti i metodi all'interno del controller, mentre l'altro progetto utilizzando il codice comune richiede ROLE_ADMIN, quindi il più facile modo per raggiungere questo è usare intercettare-url.

Quindi tenere a mente, @PreAuthorize sarà hardcoded e condiviso tra i progetti. Puoi estendere le classi e aggiungere diversi @PreAuthorize per ogni progetto, ma aggiunge ulteriore complessità.

Mi piace usare intercetta-url per proteggere un'intera area, come/utente/**, perché c'è meno rischio di rimuovere un'annotazione per errore.

Se devo aggiungere un accesso a grana fine, aggiungo un'annotazione al metodo nel controller che è già protetto da intercept-url, ma ciò accade molto raramente.