TL; DR:我如何在Spring-Data-Rest提供的扁平化REST API方法中實現細粒度的訪問控制?如何在Spring-Data-Rest中實現細粒度的訪問控制?
所以 - 我正在使用Spring的數據休息,其中有三個主要的訪問級別的API:
1)管理 - 可以看到/更新所有組
2)的所有者組 - 可以看到/更新組,一切都在它之下
3)子組的所有者 - 可以看到/只更新他的小組。沒有遞歸嵌套,只允許一個子級別。
和「基團」被暴露作爲資源(具有污物儲存庫)。
到目前爲止好 - 我已經實現了使用信息庫事件處理程序修改了一些訪問控制 - 因此在創建/寫入/刪除身邊,我覺得我很好。
現在我需要去限制某些項目的可見性的點。由於我可以使用Pre/Post Authorize註釋並引用委託人,因此獲取單個項目是可以的。
的問題就出在的findAll()方法 - 我沒有一個簡單的鉤來過濾掉特定的情況下,我不希望根據當前的主要暴露出來。例如 - 小組所有者可以通過執行GET /組來查看所有組。理想情況下,他們應該擁有他們無法訪問的項目,甚至根本不可見。
對我來說,這聽起來像在庫接口編寫自定義@Query()註解,但似乎可行不會因爲:
我需要引用主查詢。 SPeL應該被支持,但似乎完全不能用##表達式(儘管這篇博客文章提出了另外的建議:https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions)。我一般使用1.1.8.RELEASE和Evans-RELEASE訓練彈簧數據。
根據訪問級別的不同,我需要編寫的查詢將會有所不同,但不能實際包含在單個JPQL語句中(如果管理員選擇所有組,則會獲取所有(子)組與委託人的用戶相關聯)。
因此,它聽起來像我需要編寫一些自定義存儲庫實現,只是參考代碼中的委託人。沒關係 - 但是對於每個需要控制訪問權限的存儲庫來說,這看起來像是很多工作(我認爲這幾乎全部都是這些)。這適用於findAll和各種自定義搜索方法。
我接近這個錯誤嗎?是否有另一種方法來基於當前登錄的用戶動態限制項目可見性,這會更好地工作?在像spring-data-rest這樣的平面命名空間中,我會想象這是一個常見問題。
在之前的設計中,我剛剛通過暴露/ api/groups/{groupId}/...下的所有內容來解決它,並將子資源定位器用作控制對其下任何內容的訪問的單個夾點。在spring-data-rest中沒有這樣的運氣。
更新:現在有一個自定義的方法覆蓋的findAll()絆(這種方式更適合我的自定義接口上定義的其他方法)。雖然這可能是一個單獨的問題 - 我現在被阻止。當我做一個GET /組時,Spring-data並沒有調用它,而是調用原始的。奇怪的是,它使用我的查詢,如果我在界面上定義一個,並用@Query標記它(也許自定義覆蓋的內置方法不再受支持?)。
public interface GroupRepository extends JpaRepository<Group, Long>, GroupCustomRepository {}
public interface GroupCustomRepository {
Page<Group> findAll(Pageable pageable);
}
public class GroupCustomRepositoryImpl extends SimpleJpaRepository<Group, Long> implements GroupCustomRepository {
@Inject
public GroupCustomRepositoryImpl(EntityManager em) {
super(Group.class, em);
}
@Override
public Page<Group> findAll(Pageable pageable) {
MyPrincipal principal = (MyPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Page<Group> result;
if (principal.isAdmin()) {
result = findAll(pageable);
} else {
Specification<Group> spec = (root, query, cb) -> cb.or(
cb.equal(root, principal.getGroup()),
cb.and(cb.isNotNull(root.get(Group_.parentGroup)), cb.equal(root.get(Group_.parentGroup), principal.getGroup()))
);
result = findAll(spec, pageable);
}
return result;
}
}
更新2:既然不能訪問主要在@Query,我不能與一個自定義的方法來覆蓋它,我在磚牆。 @PostFilter不起作用,因爲返回對象是一個頁面而不是一個集合。
我決定只將/組隔離到管理員,並讓其他人使用@ PostFilters/@ PostAuthorizations使用不同的方法(/ groups/search/somethingSpecific)。
雖然這看起來並不像它與HAL方法非常吻合。對其他人如何用Spring-data-rest解決這些問題感興趣。
你不能使用'@ PostFilter'嗎? BTW有多個'findAll'方法。壓倒一個可能還不夠。 – zeroflagL 2014-10-30 08:33:17
試過:) @PostFilter不能和頁面一起工作 - 並且無論如何都會拋出頁面邏輯(並且可能性能很差)。看起來你只應該重寫findAll()的一個 - 否則它會將它們視爲模糊的路徑。我不知道我甚至可以支持排序和分頁,如果我只是重寫其中一種方法。 – 2014-10-30 16:46:12
你們每個人都找到了這個@DaveLeBlanc的解決方案嗎? – 2015-06-11 21:32:27