Vorläufig kam a folgende Lösung. Da mein Projekt ziemlich einfach ist, funktioniert das vielleicht nicht für ein komplexeres Projekt.
- kann entweder ein Benutzer alle oder keine der Einheiten einer bestimmten Klasse lesen
daher jede Abfrage Methode kann mit @PreAuthorize
enthält hasRole
mit Anmerkungen versehen werden.
Die Ausnahme ist die Container
Einheit in meinem Projekt. Es kann jede Unterklasse von Compound
enthalten und ein Benutzer hat möglicherweise nicht die Berechtigung, alle von ihnen anzuzeigen. Sie müssen Filter sein.
Dafür habe ich eine User
und Role
Einheit erstellt. Compound
hat eine OneToOne-Beziehung zu Role
und die Rolle ist die "read_role" für diese Compound
. User
und Role
haben eine ManyToMany-Beziehung.
@Entity
public abstract class Compound {
//...
@OneToOne
private Role readRole;
//...
}
Alle meine Repositories implementieren QueryDSLPredicateExecutor
und das wird sehr Hand hier. Anstatt benutzerdefinierte findBy-Methoden im Repository zu erstellen, erstellen wir sie nur in der Serviceebene und verwenden repositry.findAll(predicate)
und repository.findOne(predicate)
. Das Prädikat enthält die eigentliche Benutzereingabe + den "Sicherheitsfilter".
@PreAuthorize("hasRole('read_Container'")
public T getById(Long id) {
Predicate predicate = QCompoundContainer.compoundContainer.id.eq(id);
predicate = addSecurityFilter(predicate);
T container = getRepository().findOne(predicate);
return container;
}
private Predicate addSecurityFilter(Predicate predicate){
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
predicate = QCompoundContainer.compoundContainer.compound.readRole
.users.any().username.eq(userName).and(predicate);
return predicate;
}
Hinweis: QCompoundContainer
ist die "Meta-Modell" Klasse von QueryDSL erzeugt.
Endlich müssen Sie wahrscheinlich die QueryDSL Weg von Container
zu User
initialisieren:
@Entity
public abstract class CompoundContainer<T extends Compound>
//...
@QueryInit("readRole.users") // INITIALIZE QUERY PATH
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL,
targetEntity=Compound.class)
private T compound;
//...
}
Weglassen dieser letzte Schritt zu einem führen NullPointerException
kann.
Weitere Tipp: CompoundService
stellt automatisch Rolle sparen:
if (compound.getReadRole() == null) {
Role role = roleRepository.findByRoleName("read_" + getCompoundClassSimpleName());
if (role == null) {
role = new Role("read_" + getCompoundClassSimpleName());
role = roleRepository.save(role);
}
compound.setReadRole(role);
}
compound = getRepository().save(compound)
Dies funktioniert. Der Nachteil ist ein wenig offensichtlich. Das gleiche Role
ist mit jeder einzelnen Instanz der gleichen Compound
Klassenimplementierung verbunden.
Für Frage A siehe [User Schema] (http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#d0e8380]) Abschnitt –
Ich meinte es so dass ich Abfragen anpassen kann, um die Rollen zu berücksichtigen, die die aktuellen Benutzer haben, z. Es muss eine Beziehung von einer gegebenen Entität zu einer Rolle und von einer Rolle zu einem Benutzer bestehen. –
Dann werfen Sie einen Blick in die ACL http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#domain-acls und das entsprechende DB-Schema http: // static. springource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#dbschema-acl –