Meteor 的安全系統(tǒng)不需要我們?cè)诿看涡薷臄?shù)據(jù)的時(shí)候,在各自的函數(shù)里面進(jìn)行手動(dòng)檢查。
例如,對(duì)于一個(gè)博客系統(tǒng),我們常常需要做很多操作,往新帖子上添加屬性,當(dāng)發(fā)布帖子的時(shí)候進(jìn)行特定檢查。這些操作都是圍繞帖子(post)這個(gè)對(duì)象進(jìn)行的,所以我們應(yīng)該為帖子設(shè)置一個(gè)專(zhuān)門(mén)的函數(shù)進(jìn)行安全檢查。
但在另一方面,我們又不希望為修改帖子或刪除帖子這些簡(jiǎn)單的操作編寫(xiě)特定的函數(shù)。我們只需要在這些操作之前,檢查用戶(hù)是否有權(quán)限就可以了。這時(shí)我們就需要用到允許(allow)和拒絕(deny)回調(diào)函數(shù)。
這些回調(diào)函數(shù)可以方便地讓我們定義哪些數(shù)據(jù)可以被修改,哪些可以被刪除。另外,這些回調(diào)函數(shù)還整合了用戶(hù)系統(tǒng)(account system),用以判斷權(quán)限。
我們可以根據(jù)需要定義多個(gè)允許 allow
回調(diào)函數(shù)。但是我們只需要其中_至少有一個(gè)_返回 true
就可以讓操作通過(guò)驗(yàn)證。當(dāng) Post.insert
被調(diào)用時(shí)(無(wú)論是在我們 app 的客戶(hù)端代碼調(diào)用,還是在瀏覽器控制臺(tái)調(diào)用),服務(wù)器會(huì)逐個(gè)運(yùn)行為 insert 設(shè)置的允許(allow)回調(diào)函數(shù),直到其中一個(gè)返回 true
為止。如果這樣的允許回調(diào)函數(shù)不存在,服務(wù)器就不會(huì)允許 insert 操作,并給客戶(hù)端返回一個(gè) 403
錯(cuò)誤。
類(lèi)似地,我們也可以定義一個(gè)或者多個(gè)拒絕 deny
回調(diào)函數(shù)。如果其中一個(gè)回調(diào)函數(shù)返回 true
,操作就會(huì)被取消,并且返回 403
。這意味著,一個(gè)成功的 insert 操作要求至少一個(gè)返回 true
的允許 allow
回調(diào)函數(shù),并且_所有_拒絕 deny
回調(diào)函數(shù)都返回 false
。
<%= diagram "allow_deny", "注:n/e 表示該函數(shù)沒(méi)有被執(zhí)行" %>
更直觀地說(shuō),Meteor 從拒絕回調(diào)函數(shù)開(kāi)始,然后是 allow
函數(shù),逐一執(zhí)行,直到有一個(gè)返回 true
。
這個(gè)模式的一個(gè)實(shí)際例子就是,建立兩個(gè) allow()
允許回調(diào)函數(shù),一個(gè)用于檢查帖子是否屬于當(dāng)前用戶(hù),另外一個(gè)用于檢查當(dāng)前用戶(hù)是否管理員。如果當(dāng)前用戶(hù)是管理員,由于至少有一個(gè)回調(diào)函數(shù)返回 true
,那就確保他們可以更新任何帖子。
還記得我們前面說(shuō)過(guò),數(shù)據(jù)庫(kù)的可變函數(shù)(例如 .update()
)使用了一種延遲補(bǔ)償技術(shù)。所以,當(dāng)你嘗試從瀏覽器的控制臺(tái)刪除一篇不屬于你的帖子的時(shí)候,你會(huì)看到帖子短時(shí)間內(nèi)消失,但馬上又會(huì)重新出現(xiàn)。這是因?yàn)樘硬](méi)有真正從后臺(tái)刪除,刪除操作被后臺(tái)拒絕了。
這樣的行為在控制臺(tái)上不是問(wèn)題(開(kāi)發(fā)者可以隨意支配數(shù)據(jù)進(jìn)行開(kāi)發(fā))。但是,你需要確保這樣的行為不會(huì)出現(xiàn)在用戶(hù)界面上。比如說(shuō),你需要確保對(duì)于用戶(hù)不能刪除的帖子,用戶(hù)不會(huì)看到刪除鍵。
慶幸的是,你可以在客戶(hù)端和服務(wù)端使用一樣的代碼進(jìn)行權(quán)限管理(例如,你可以寫(xiě)一個(gè) canDeletePost(user, post)
函數(shù),把它放在一個(gè)共享的 /lib
文件夾下面),這樣做通常不需要太多額外的代碼。
只有來(lái)自客戶(hù)端的數(shù)據(jù)庫(kù)操作需要被權(quán)限系統(tǒng)驗(yàn)證。服務(wù)端的_所有_操作都被認(rèn)定為安全的,不需要被權(quán)限系統(tǒng)驗(yàn)證。
這意味著如果你創(chuàng)建了一個(gè)服務(wù)端函數(shù) deletePost
,而且這個(gè)函數(shù)可以被客戶(hù)端執(zhí)行,那么任何用戶(hù)都可以刪除任何帖子了。因此,你可能不想那么做,除非你在函數(shù)中也驗(yàn)證用戶(hù)權(quán)限。
更多建議: