2015-04-17 9 views
9

Sto tentando di implementare il controllo dell'accesso a grana fine sfruttando ancora il riposo dati Spring.Controllo accesso repository in Spring Data Rest basato su utente princpal

Sto lavorando per rendere sicuro un CrudRepository in modo che gli utenti possano modificare o inserire solo i dati che appartengono a loro. Sto facendo uso di @PreAuthorize/@PostAuthorize e @PreFilter/@PostFilter per bloccare l'accesso al principale corrente.

Finora il mio repository appare così.

public interface MyRepository extends CrudRepository<MyObject, Integer> { 

    @PreAuthorize("#entity.userId == principal.id") 
    @Override 
    <S extends MyObject> S save(S entity); 

    @PreFilter("filterObject.userId === principal.id") 
    @Override 
    <S extends MyObject> Iterable<S> save(Iterable<S> entities); 

    @PostAuthorize("returnObject.userId == principal.id") 
    @Override 
    MyObject findOne(Integer integer); 

    @PostFilter("filterObject.userId == principal.id") 
    @Override 
    Iterable<MyObject> findAll(); 

} 

Mentre questo è un po 'noioso, sembra realizzare ciò che sto cercando. (Se qualcuno conosce un modo migliore, non esitate a farmi sapere!)

Dove sto correndo in problemi è con delete(), count() e exists()

@Override 
    long count(); 

    @Override 
    void delete(Integer integer); 

    @Override 
    void delete(MyObject entity); 

    @Override 
    void deleteAll(); 

    @Override 
    boolean exists(Integer integer); 

Questi metodi prendere un parametro Integer ID o proprio nessuno. Sembra che dovrei prima selezionare l'entità con l'ID di input e quindi eseguire il controllo di autenticazione.

Questo tipo di autorizzazione è possibile all'interno del repository?

Grazie

Edit:

Grazie a ksokol questo sembra funzionare ora.

ho aggiunto un nuovo bean a una classe di @Configuration

@Bean 
public EvaluationContextExtension securityExtension() { 
    return new SecurityEvaluationContextExtensionImpl(); 
} 

Questo bean estende EvaluationContextExtensionSupport e sovrascrive getRootObject per restituire un SecurityExpressionRoot che tiene il mio principale personalizzato.

public class SecurityEvaluationContextExtensionImpl extends EvaluationContextExtensionSupport { 
@Override 
public String getExtensionId() { 
    return "security"; 
} 

@Override 
public Object getRootObject() { 
     Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
     return new SecurityExpressionRoot(authentication){}; 
    } 
} 

risposta

14

Come di Spring Security 4.0 è possibile accedere contesto di sicurezza nelle query primavera dati JPA.

Aggiungi SecurityEvaluationContextExtension fagioli al vostro contesto di bean:

@Bean 
public SecurityEvaluationContextExtension securityEvaluationContextExtension() { 
    return new SecurityEvaluationContextExtension(); 
} 

Ora si dovrebbe essere in grado di accedere Principal nelle query primavera dati:

@Query("select count(m) from MyObject as m where m.user.id = ?#{ principal?.id }") 
@Override 
long count(); 

@Modifying 
@Query("delete from MyObject as m where m.id = ?1 and m.user.id = ?#{ principal?.id }") 
@Override 
void delete(Integer integer); 

@Modifying 
@Query("delete from MyObject as m where m.id = ?1 and m.user.id = ?#{ principal?.id }") 
@Override 
void delete(MyObject entity); 

@Modifying 
@Query("delete from MyObject as m where m.user.id = ?#{ principal?.id }") 
@Override 
void deleteAll(); 

@Query("select 1 from MyObject as m where m.id = ?1 and m.user.id = ?#{ principal?.id }") 
@Override 
boolean exists(Integer integer); 

Attenzione. Le query potrebbero contenere errori. Non ho avuto il tempo di testarlo.

+0

Grazie ksokol, queste query JPQL sovrascriveranno il comportamento implementato di runtime predefinito? Come stai riferendo i parametri del metodo, stai usando? 1 – francis

+1

Sì. Sostituiscono le query generate dal runtime. Usando '?1' ecc. Stai facendo riferimento ai parametri del metodo all'interno delle tue query. Vedi [Uso di @Query] (http://docs.spring.io/spring-data/jpa/docs/1.8.0.RELEASE/reference/html/#jpa.query-methods.at-query) per ulteriori informazioni. –

1

Si può ottenere anche implementando i controlli nei gestori di eventi del repository Spring personalizzati. Vedi @HandleBeforeCreate, @HandleBeforeUpdate, @HandleBeforeDelete.

In alternativa, è possibile utilizzare espressioni basate su autorizzazioni, ad es. con ACL o quelli personalizzati, è possibile scrivere @PreAuthorize("hasPermission(#id, 'MyObject', 'DELETE')").

Problemi correlati