場景模擬
-
場景一
只允許資源的所有者才能對資源進行操作(CRUD)茁计。比如切黔,jack在某博客平臺寫了一篇私密文章,只有自己可以對這篇文章進行增刪查改的操作笙以;
-
場景二
允許指定個人或者角色也能對資源進行操作。比如冻辩,jack邀請他的好朋友mason對文章進行查看和修改猖腕;
方案一
最簡單和最直接的就是,在web層接收到操作請求后恨闪,在執(zhí)行這個操作前倘感,對請求的合法性進行校驗。比如咙咽,查詢當(dāng)前需要操作的資源是否歸屬當(dāng)前session中的已登錄用戶老玛;或者查詢當(dāng)前需要操作的資源是否是允許操作的其它用戶。
String loginUser = session.get("username");
// 增加水平越權(quán)校驗
if(!checkAuthority(loginUser,articleId)){
return false;
}
// 執(zhí)行正常的操作
// 當(dāng)前登錄者是否是資源的所有者
private Boolean checkAuthority(String loginUser, String articleId){
String articleOwner = articleService.getOwner(articleId);
return Objects.equals(loginUser, articleOwner);
}
// 當(dāng)前登錄者是否有操作權(quán)限
private Boolean checkAuthority(String loginUser, String articleId){
int count = articleService.getLegalUser(loginUser, articleId);
return count > 0 ? Boolean.TRUE : Boolean.FALSE;
}
這種方案的優(yōu)點是實現(xiàn)簡單钧敞,邏輯清晰蜡豹;但是缺點也很明顯,需要對每一個請求都加上這種操作溉苛,很是繁瑣余素,而且多了一次數(shù)據(jù)庫查詢,效率肯定有所下降炊昆;
方案二
我們可以直接將登錄者的信息傳遞到SQL層面進行校驗,比如場景一我們可以在原SQL最后加上一句來限制資源的操作威根。
select * from artile where article_id = #{articleId}
and author = #{loginUser}
如果是場景二的話凤巨,我們需要多關(guān)聯(lián)一張表。
select * from artile a join author_guest g on a.author = g.author where article_id = #{articleId}
and g.guest = #{loginUser}
其中author_guest
存放的是作者邀請的朋友之間的關(guān)系映射表洛搀。
這種方案的優(yōu)點是沒有增加額外的Java代碼敢茁,沒有增加額外的數(shù)據(jù)庫查詢,比較簡潔優(yōu)雅留美;但是缺點是需要改動SQL彰檬,增加了SQL的復(fù)雜性,而且有時一個SQL是供多塊邏輯共用的谎砾,A模塊需要鑒權(quán)逢倍,B模塊不需要鑒權(quán),那就要重新寫一份相同的SQL或者在SQL上加分支了景图,那SQL會變得更難以理解和維護较雕。
除此之外,好像還沒法區(qū)分沒有數(shù)據(jù)和沒有權(quán)限兩種操作異常情況,只能給前端反饋操作異常的提示亮蒋,不是很友好扣典。