2015-04-17 18 views
9

Tôi đang cố gắng thực hiện kiểm soát truy cập hạt mịn trong khi vẫn tận dụng phần còn lại của dữ liệu Spring.Kiểm soát truy cập kho lưu trữ trong Spring Data Rest dựa trên người dùng nguyên tắc

Tôi đang làm việc để bảo mật CrudRepository để người dùng chỉ có thể sửa đổi hoặc chèn dữ liệu thuộc về họ. Tôi đang sử dụng @PreAuthorize/@PostAuthorize@PreFilter/@PostFilter để khóa quyền truy cập xuống hiệu trưởng hiện tại.

Kho lưu trữ của tôi trông như thế này.

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(); 

} 

Trong khi điều này hơi tẻ nhạt, có vẻ như tôi đã đạt được những gì tôi theo đuổi. (Nếu có ai biết một cách tốt hơn, cảm thấy tự do để cho tôi biết!)

Nơi tôi đang chạy vào vấn đề là với delete(), count()exists()

@Override 
    long count(); 

    @Override 
    void delete(Integer integer); 

    @Override 
    void delete(MyObject entity); 

    @Override 
    void deleteAll(); 

    @Override 
    boolean exists(Integer integer); 

Những phương pháp này hoặc lấy một tham số Integer ID hoặc không có gì cả. Có vẻ như tôi sẽ phải chọn thực thể đầu tiên với ID đầu vào và sau đó thực hiện kiểm tra auth.

Loại ủy quyền này có thể có trong kho lưu trữ không?

Cảm ơn

Edit:

Nhờ ksokol này dường như được làm việc ngay bây giờ.

tôi đã thêm một bean mới cho một lớp @Configuration

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

đậu này mở rộng EvaluationContextExtensionSupport và ghi đè getRootObject để trả về một SecurityExpressionRoot chứa chủ yếu tùy chỉnh của tôi.

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

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

Trả lời

14

Kể từ Spring Security 4.0 bạn có thể truy cập ngữ cảnh bảo mật trong truy vấn JPA dữ liệu Spring.

Thêm SecurityEvaluationContextExtension đậu để bối cảnh đậu của bạn:

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

Bây giờ bạn sẽ có thể truy cập vào Principal trong các truy vấn dữ liệu mùa xuân của bạn:

@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); 

Thận trọng. Truy vấn có thể có lỗi. Tôi không có thời gian để kiểm tra nó.

+0

Cảm ơn ksokol, các truy vấn JPQL này sẽ ghi đè hành vi được thực thi mặc định trong thời gian chạy? Làm thế nào bạn tham khảo các tham số phương pháp, bạn đang sử dụng? 1 – francis

+1

Có. Chúng ghi đè các truy vấn được tạo thời gian chạy. Bằng cách sử dụng '?1' vv bạn đang tham khảo các tham số phương thức bên trong các truy vấn của bạn. Xem [Sử dụng @Query] (http://docs.spring.io/spring-data/jpa/docs/1.8.0.RELEASE/reference/html/#jpa.query-methods.at-query) để biết thêm thông tin. –

1

Cũng có thể đạt được bằng cách thực hiện kiểm tra của bạn trong trình xử lý sự kiện lưu trữ Spring tùy chỉnh của bạn. Xem @HandleBeforeCreate, @HandleBeforeUpdate, @HandleBeforeDelete.

Hoặc, bạn có thể sử dụng biểu thức dựa trên quyền, ví dụ: với ACL hoặc tùy chỉnh của bạn, bạn có thể viết @PreAuthorize("hasPermission(#id, 'MyObject', 'DELETE')").

Các vấn đề liên quan