Hiện tại đã có giải pháp sau. Vì dự án của tôi khá đơn giản nên điều này có thể không hoạt động cho một dự án phức tạp hơn.
- người dùng có thể hoặc là đọc tất cả hoặc không ai trong số các đối tượng của một lớp nào đó
do đó bất kỳ phương pháp truy vấn có thể được chú thích với @PreAuthorize
chứa hasRole
.
Trường hợp ngoại lệ là thực thể Container
trong dự án của tôi. Nó có thể chứa bất kỳ lớp con nào của Compound
và người dùng có thể không có đặc quyền để xem tất cả chúng. Chúng phải là bộ lọc.
Vì điều đó tôi đã tạo một thực thể User
và Role
. Compound
có mối quan hệ OneToOne với Role
và vai trò đó là "read_role" cho số Compound
đó. User
và Role
có mối quan hệ ManyToMany.
@Entity
public abstract class Compound {
//...
@OneToOne
private Role readRole;
//...
}
Tất cả kho lưu trữ của tôi thực hiện QueryDSLPredicateExecutor
và rất dễ dàng ở đây. Thay vì tạo các phương thức findBy tùy chỉnh trong kho lưu trữ, chúng tôi chỉ tạo chúng trong lớp dịch vụ và sử dụng repositry.findAll(predicate)
và repository.findOne(predicate)
. Vị từ giữ đầu vào người dùng thực tế + "bộ lọc bảo mật".
@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;
}
Lưu ý: QCompoundContainer
là lớp "meta-mô hình" được tạo ra bởi QueryDSL.
Cuối cùng bạn có thể cần phải khởi tạo con đường QueryDSL từ Container
để User
:
@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;
//...
}
Bỏ bước cuối cùng này có thể dẫn đến một NullPointerException
.
Tiếp tục gợi ý: CompoundService
tự động thiết lập vai trò trên tiết kiệm:
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)
này hoạt động. Nhược điểm là một chút rõ ràng. Cùng một Role
được liên kết với mọi trường hợp duy nhất của cùng một thực hiện lớp Compound
.
Đối với câu hỏi A see [User Schema] (http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#d0e8380]) phần –
Ý tôi là tôi có thể điều chỉnh các truy vấn để xem xét vai trò của người dùng hiện tại, ví dụ: phải có mối quan hệ từ một thực thể nhất định với vai trò và từ vai trò đến người dùng. –
Sau đó, hãy xem ACL http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#domain-acls và lược đồ DB thích hợp http: // tĩnh. springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#dbschema-acl –