經(jīng)過多年開發(fā),56 次發(fā)布,130 萬下載,并且超過 2800 的主動關(guān)注?Bouncer?終于來到了 1.0 版本。 在相當(dāng)長的一段時間里,它一直非常可靠和穩(wěn)定,并被世界各地?zé)o數(shù)的 app 用于生產(chǎn)。
這是我個人的更新,包含了我多年來的一些思考 —— 從最初到最終發(fā)行。關(guān)于如何每天使用 Bouncer 的技術(shù)信息,請查看?Bouncer?或者在?Bouncer 聽我和馬特?斯托弗討論。
什么是 Bouncer?Bouncer
在開始我的個人旅程之前,這里先簡要介紹一下 Bouncer 是什么,以及它如何融入更大的 laravel 生態(tài)系統(tǒng)。
Bouncer 是一個開源包,用于動態(tài)管理數(shù)據(jù)庫中的角色和權(quán)限,與 Laravel 的 Gate 完全集成。
在不深入細(xì)節(jié)的情況下,以下是其一些主要功能的簡短列表:
-
Bouncer::allow($user)->to('access-dashboard');
-
Bouncer::allow($user)->to('view',?Invoice::class); Bouncer::allow($user)->to('delete',?$invoice);
-
Bouncer::allow('admin')->everything(); Bouncer::assign('admin')->to($user);
-
Bouncer::allow($user)->to('view',?Invoice::class); Bouncer::forbid($user)->to('view',?$confidentialInvoice);
-
Bouncer::allow($user)->toOwn(Post::class);
-
Bouncer::scope()->to($tenantId);
-
Bouncer::cache();
… 還有更多。有關(guān)詳細(xì)信息,請查看Bouncer,或只需瀏覽Bouncer.
Bouncer 最初的想法
早在 2015 年 8 月,Bouncer?添加了一個 Bouncer,稱為?Gate。這提供了一個很好用的 API,用于應(yīng)用程序中定義各種操作的權(quán)限檢查,Bouncer?和完整的?Bouncer,以及根據(jù)您定義的內(nèi)容在 Bouncer。
當(dāng)我開始使用它時,我就知道這將是所有 Laravel 應(yīng)用程序的 Bouncer 的未來。 真是太好了,Taylor 對清晰和直觀的 API 有這種驚人的感覺,而「Gate」抽象真正地揭示了這一點。
然而,內(nèi)置授權(quán)系統(tǒng)缺少一件事:動態(tài)權(quán)限,存儲在數(shù)據(jù)庫中。 構(gòu)建 Gate 的方式,所有檢查都由應(yīng)用程序中定義的硬編碼函數(shù)執(zhí)行,因此無法讓您的管理員在運(yùn)行時通過某些儀表板 ui 控制其中任何一個。 正如泰勒的 Bouncer 明確指出:
[內(nèi)置 Gate] 為組織邏輯提供了一種結(jié)構(gòu),該邏輯授權(quán)對實體進(jìn)行操作。 它沒有對「用戶角色」的定義做出任何決定。
當(dāng)時,還有許多其他流行的 Bouncer 操作系統(tǒng)支持在運(yùn)行時調(diào)整權(quán)限,但它們有一個主要缺點:它們都是在 Laravel 的 Gate 之前構(gòu)建的。它們是完全分離的系統(tǒng);如果您決定使用它們,你將放棄 Laravel 的 gate 提供的所有細(xì)節(jié)和漂亮的集成。
因此,我決定構(gòu)建一個開源包,它可以讓您兩全其美:動態(tài)數(shù)據(jù)庫驅(qū)動的權(quán)限,與 Laravel 的 gate 完全集成。Bouncer,使其更加簡化和可預(yù)測,從而更容易將這些功能存儲在數(shù)據(jù)庫中。
Bouncer 的名稱和 logo
我很早就想到了「保鏢」(Bouncer) 這個名字。 Bouncer 的職責(zé)是在門口提供安全保障并檢查人們的權(quán)限。 所以這是與 Laravel 中的「Gate」非常自然的配對。
有趣的是,當(dāng)時與我合作的標(biāo)志設(shè)計師(不是以英語為母語的人)沒有得到參考。 以下是他設(shè)計的 Bouncer:
右邊的兩個顯然是受到彈跳動作的啟發(fā)。
在快速闡明了保鏢這個詞的含義之后,我們開始迭代實際的保鏢 logo。 我們嘗試了友好的保鏢、威脅的保鏢、大胡子的保鏢、方下巴的保鏢,以及大量不同的變體。 這里僅僅是少數(shù):
我非常喜歡我們最終得到的結(jié)果:
它散發(fā)出強(qiáng)烈的安全感,但它的圓潤讓人感覺更友好,威脅更小
技術(shù)基礎(chǔ)
Bouncer’s 的存在理由是與 Laravel 的 gate 無縫集成的。為了實現(xiàn)這一點,我心中的只有一個目標(biāo):在為用戶分配角色和能力時,您只需和 Bouncer?進(jìn)行交互。對于實際的授權(quán)檢查,整個系統(tǒng)中 Laravel 的鉤子應(yīng)該自動工作,而不需任何特殊的 Bouncer 語法。ically, without any special Bouncer syntax.
將 Bouncer 掛鉤到 Laravel 的 gate 檢查方式是相當(dāng)簡單的。Gate?讓你定義?Bouncer,它將會在任何您定義的檢查之前被調(diào)用:如果您的 before 回調(diào)允許或不許與某個操作,則不會運(yùn)行進(jìn)一步檢查。
雖然 before 回調(diào)最初是為 「允許管理員執(zhí)行所有操作」之類的東西而設(shè)計的,但我立即意識到這將是連接動態(tài)檢查的理想場所,允許我查詢數(shù)據(jù)庫以獲得任何權(quán)限。這就是它最初的工作方式(我們后來將其切換為使用 Bouncer – 你可以閱讀更多關(guān)于 Bouncer)
文檔
從一開始,文檔對我來說就非常重要。 開源項目的生死取決于他們的文檔,所以我希望 Bouncer 的文檔盡可能做到最好。尤其是在 Laravel 生態(tài)系統(tǒng)中,Taylor 為細(xì)致的文檔設(shè)定了極高的標(biāo)準(zhǔn)。
在某種程度上,清晰的文檔有時甚至比代碼本身更重要。如果不告訴你的用戶如何使用你的工具,他們中很少有人會使用源代碼來解決這個問題。他們只會繼續(xù)做下一件事。
我將 Bouncer 的成功很大程度上歸功于清晰的文檔,但在這方面還有很多工作要做。作為創(chuàng)建者,對整個謎題有一個清晰的了解,很容易忘記剛接觸該工具的人會遇到什么困難。
例如:如前所述,Bouncer 僅用于為用戶分配角色和權(quán)限。實際的授權(quán)檢查將像在任何標(biāo)準(zhǔn) Laravel 應(yīng)用程序中一樣處理。所以我想我不必重復(fù)所有這些,因為 Bouncer。盡管如此,我仍然看到人們?yōu)榇丝嗫鄴暝K麄冊O(shè)置了自己的角色和權(quán)限,然后不知道從哪里開始。這是我仍然想在文檔中充實的一個領(lǐng)域。
準(zhǔn)備發(fā)布
將 1.0 版本推遲到現(xiàn)在對我的用戶造成了傷害。 Bouncer 多年來一直很穩(wěn)定,并在世界各地的生產(chǎn)中積極使用。 然而,我總是猶豫要不要發(fā)布它,因為我知道我想添加的東西太多了。 我在 Bouncer 上與 Matt 詳細(xì)討論了這個問題:我掉進(jìn)了想要在發(fā)布之前讓它變得完美的陷阱,這顯然是 不可能的。 正如伏爾泰 Bouncer:「完美是良好的敵人」。
因此,當(dāng)我發(fā)布 Bouncer 1.0 版時,我仍然希望在初始版本中包含 2 個出色的功能,但沒有成功:
-
每個模型的角色。 很長一段時間以來,人們一直在吵著要一種方法,只為給定的模型(或模型類)分配角色給用戶。 這是該代碼的樣子:
//?注意:這還沒有實現(xiàn) Bouncer::allow('editor')->to(['view',?'edit'])->everything(); Bouncer::assign('editor')->to($user)->for(Invoice:class);
這樣,用戶就可以查看和編輯所有發(fā)票,但不能做其他任何事情。 當(dāng)然,這現(xiàn)在可以在沒有角色的情況下直接完成,但通過角色來完成會提供另一層靈活性。
我已經(jīng)嘗試過多次解決這個問題,但結(jié)果非常棘手,因為緩存變成了一場真正的噩夢。 我仍然希望有一天能解決它。 走著瞧。
-
能力限制。 允許對給定能力進(jìn)行任意限制將增加更精細(xì)的控制:
//?注意:這還沒有實現(xiàn) Bouncer::allow($user) ->to('view',?Post::class) ->where('is_confidential',?false);
如果你探索過 Bouncer 的源碼,你會發(fā)現(xiàn)一些 Bouncer 和 Bouncer 我開始實現(xiàn)這個的地方。 它遠(yuǎn)未完成,但請繼續(xù)關(guān)注。
總的來說,Bouncer 處于一個非常好的位置。每個好的產(chǎn)品都有一個漫長的路線圖,認(rèn)為我可以在發(fā)布 1.0 之前走到這條路的盡頭,這是愚蠢和不切實際的。
享受使用它!
好了,到此為止。我希望您嘗試在您的應(yīng)用程序中使用?Bouncer,并享受使用它。 Bouncer 的 API 被設(shè)計的像散文一樣,每個方法調(diào)用讀起來都像是一個合適的英文句子。試一試,如果您也有這種感覺,請告訴我!
【相關(guān)推薦:Bouncer】