国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何從零設(shè)計(jì)結(jié)構(gòu)清晰、操作友好的權(quán)限管理模塊

kel / 2551人閱讀

摘要:同時(shí)將用戶關(guān)聯(lián)到用戶組,從而可以在不斷變動(dòng)權(quán)限的情況下,配置一次對(duì)應(yīng)關(guān)系,將用戶權(quán)限限制到單個(gè)上。這樣在返回?cái)?shù)據(jù)的時(shí)候,所有記錄均為對(duì)其具有操作權(quán)限的對(duì)象。當(dāng)然是天生的組件化設(shè)計(jì)理念。

前言

在開講之前,先列舉幾個(gè)場(chǎng)景:
場(chǎng)景一
Hi,今天那個(gè)銷售總監(jiān)說(shuō)要設(shè)立幾個(gè)銷售經(jīng)理的職位,然后每個(gè)經(jīng)理管理自己小組的銷售員,我們把用戶的銷售數(shù)據(jù)按組分開來(lái)吧。
場(chǎng)景二
Mario,今天那個(gè)市場(chǎng)部的說(shuō)要分立幾個(gè)板塊,公眾號(hào)的管理所有文章投稿評(píng)論,推廣管各平臺(tái)宣傳策略方案與實(shí)施,對(duì),競(jìng)品的相關(guān)資料數(shù)據(jù)也要分立出來(lái),我們要把這些分開來(lái)。之前討論的銷售部的事情和這個(gè)沒關(guān)系哦。
場(chǎng)景三
那個(gè),xx店的店主說(shuō),他管理的兩家門店,想同時(shí)處理兩家店的事情,需要兼顧兩家的銷售、采購(gòu)的數(shù)據(jù)。人家提的需求場(chǎng)景有道理,你給他做一下吧,對(duì)了,不要影響其他店的管理哦!
場(chǎng)景四
今天總部的運(yùn)營(yíng)小x說(shuō),他們需要以門店、部門、單個(gè)用戶的角度看所有的運(yùn)營(yíng)數(shù)據(jù),給他們做一下吧,每天導(dǎo) excel 要瘋了。

開始

當(dāng)我們談及權(quán)限的時(shí)候,很容易想到在用戶發(fā)起請(qǐng)求時(shí),對(duì)接口做一層權(quán)限驗(yàn)證,或者是對(duì)數(shù)據(jù)庫(kù)讀寫限制權(quán)限,簡(jiǎn)單粗暴。因?yàn)槭且杂脩舨僮鳛槌霭l(fā)點(diǎn)進(jìn)行限制,所以我們?cè)谝粋€(gè)接口的 handler 中定義:

if not user in [‘xxx’, ‘yyy’, ‘zzz’]:
          return ‘has no permission!’

或者在處理數(shù)據(jù)模型的 model 層定義:

access_users  = [‘xxx’, ‘yyy’, ‘zzz’]

這樣限制住了用戶的操作行為。不過(guò)這個(gè)硬編碼的形式簡(jiǎn)直慘不忍睹,今天加一個(gè)接口,我們?cè)?handler 代碼中來(lái)一段這個(gè)權(quán)限定義,明天另一個(gè) handler 的權(quán)限變動(dòng)了,我們?cè)偃ジ囊幌履莻€(gè)代碼。你說(shuō)寫在一個(gè)裝飾器中統(tǒng)一管理,ok,那么在添加、修改 handler 的同時(shí),還要去找到對(duì)應(yīng)的具有該權(quán)限的用戶,在裝飾器中進(jìn)行相關(guān)定義。在一個(gè)產(chǎn)品不斷迭代的情景下,這樣是不能被接受的。所以我們有必要引入一個(gè)模型來(lái)規(guī)范化權(quán)限控制。

結(jié)構(gòu)化管理

通過(guò)以上情景,我們很容易得到一種權(quán)限結(jié)構(gòu)模型(參考 django)以 user(單一用戶)、group(用戶組)、permissions(單一權(quán)限)三層兩兩之間多對(duì)多的關(guān)系,實(shí)現(xiàn)了當(dāng)用戶請(qǐng)求接口 APIa,此時(shí)進(jìn)行獲取用戶,獲取用戶所屬組,獲取所屬組所具備的權(quán)限,若獲取不到記錄,則限制掉此次請(qǐng)求。運(yùn)用這個(gè)模型,我們每次將 permissions 定義成:module、function 的形式,同時(shí)定義 request method 。這樣將具有權(quán)限的 group 關(guān)聯(lián)到一個(gè) permission(即一個(gè) handler)上。同時(shí)將用戶關(guān)聯(lián)到用戶組,從而可以在不斷變動(dòng)權(quán)限的情況下,配置一次對(duì)應(yīng)關(guān)系,將用戶權(quán)限限制到單個(gè) handler 上。

用 python 的同學(xué)知道,由于 python decorator @的語(yǔ)法糖,我們很喜歡用這種形式來(lái)處理這些與業(yè)務(wù)邏輯無(wú)關(guān)的代碼,例如:日志記錄、檢查緩存、檢查 user session等。有時(shí)候在一個(gè)方法裝飾器寫的像蓋樓一樣,稍不留神就忘記了。有時(shí)候開發(fā)者對(duì)項(xiàng)目不熟悉,在寫一個(gè)新的接口之后,配置了權(quán)限,卻忘記加裝飾器,導(dǎo)致這部分一直沒有被限制。

@route()
@login_required
@check_cache
@add_log
@permission_verify
@transaction.atomic
def interface_a():

所以在這里引入一個(gè)中間件,專門處理這個(gè)事情,不必每次增加額外代碼。

中間件運(yùn)行發(fā)生在后端 route dispatching 的時(shí)候,每次的請(qǐng)求我們根據(jù)請(qǐng)求的 session 找到 user、找到對(duì)應(yīng)的 user group, 再找到 permissions,通過(guò)定義的具有權(quán)限 module function 與請(qǐng)求的 handler 比對(duì),若不同則限制掉。

def permission_middleware():
    permissions =  request.get.user_permissions()
    if ‘{}_{}’.format(handler.__class__, handler.func_name) not in permissions:
        return permission_denied

這樣后端限制邏輯比較結(jié)構(gòu)化,節(jié)省了很多麻煩,方便修改和管理。同時(shí)具有較好的擴(kuò)展性,我們將 user 定義為單一用戶對(duì)象,將 permissions 看作單一 handler 對(duì)象,可以把所有門店、部門、小組、小群體等均劃分到 group 一層 。幾乎大部分的業(yè)務(wù)需求均可以對(duì)應(yīng)實(shí)現(xiàn)。邏輯準(zhǔn)確,嗯,很完美。

限制閉環(huán),對(duì)象細(xì)化

第二天 PM 來(lái)了,說(shuō) xx 部門的小 x 講他們部門里面的工作內(nèi)容需要分類,(我在點(diǎn)頭,心里想:嗯嗯,我給你們每一個(gè)分類加一個(gè) group 配置 user 權(quán)限)一個(gè)工作分類有許多工作者,有一個(gè)管理者,管理者需要看所有工作者的工作進(jìn)度,工作內(nèi)容管理者也同樣可以進(jìn)行(心里想:嗯嗯,我再加一個(gè)管理者的 group 所有權(quán)限一樣,多帶帶加一個(gè)工作進(jìn)度查看的權(quán)限)同時(shí)!1分類下的管理者,還可以看2、3工作分類下的小 y 小 z 的工作進(jìn)度!(我心里想:what?這不科學(xué)吧)PM 繼續(xù)說(shuō),因?yàn)樗麄児ぷ饕獙?duì)接,是需要查看的功能(我想:那管理者不作分類不就好了,所有的內(nèi)容都可以看)并不能全部看到!PM 接著說(shuō),他的主要工作還是本分類下的工作內(nèi)容,只是查看一下其他分類下的幾個(gè)人的進(jìn)度,你不能給他把所有人的內(nèi)容都展示出來(lái)吧,況且有些還是保密的。

這確實(shí)是一個(gè)問題,不僅僅是在這種特殊的情況,只要涉及到針對(duì)某一個(gè)用戶,或者某一個(gè)具體內(nèi)容做操作限制,就是實(shí)現(xiàn)不了的。經(jīng)過(guò)輾轉(zhuǎn)反側(cè),發(fā)現(xiàn)我們之前做的只是將權(quán)限限制在操作行為上,沒有形成閉環(huán),操作哪些對(duì)象沒有定義。每一次限制默認(rèn)是所有對(duì)象。這樣雖然方便管理,但是有些場(chǎng)景不能滿足需求。于是引入權(quán)限操作對(duì)象范圍的概念:
在之前的 permissions 一層上加入:

是否有對(duì)象粒度限制

限制的哪個(gè) model 的 object

可操作的object id list。

由于這部分是對(duì)于數(shù)據(jù)過(guò)濾的處理,所以我們無(wú)法在中間件完成這個(gè)操作。將這部分放入數(shù)據(jù)處理層(DAO 層)進(jìn)行過(guò)濾是個(gè)不錯(cuò)的主意。首先我們?cè)跀?shù)據(jù)處理方法中,在上下文獲取本次請(qǐng)求的 user 對(duì)象,按老辦法將他的 permissions 統(tǒng)統(tǒng)獲取到,這時(shí),按照我們預(yù)先定義的:是否有對(duì)象粒度限制進(jìn)行判斷,需要限制則根據(jù)當(dāng)前處理的 model 過(guò)濾出操作的 object id list。這樣在返回?cái)?shù)據(jù)的時(shí)候,所有記錄均為對(duì)其具有操作權(quán)限的對(duì)象。

object_id_list = request.user.permissions.get_object_id_list()
if need_limit_object and model == request.user.permissions.get_model:
        sql = ‘select * from model where id in {}’.format(tuple(object_id_list))
        return fetch_data(sql)

現(xiàn)在我們滿足了所有(至少是目前為止所遇到的)業(yè)務(wù)需求,后續(xù)權(quán)限的所有需求也可以按照這個(gè)思路進(jìn)行相關(guān)配置處理,并得以解決(美好的愿望^_^)。

前端限制提高體驗(yàn)

至此,我們開發(fā)工作會(huì)變得很愉快,邏輯清晰且結(jié)構(gòu)嚴(yán)謹(jǐn)。與此同時(shí),給 c 端用戶的體驗(yàn)就是,哪里不會(huì)點(diǎn)哪里,點(diǎn)完哪里不給你。給一個(gè)美如畫的頁(yè)面或者是彈窗還算好的,跳個(gè)403、404或是500想必也見過(guò)。此時(shí)用戶只有一句 mmp,什么破玩意不玩了。

所以,權(quán)限在前端預(yù)先限制勢(shì)在必行,好在我們多數(shù)情況下用到了模版引擎,很方便的在頁(yè)面上進(jìn)行權(quán)限判斷。在服務(wù)器端渲染頁(yè)面的時(shí)候,根據(jù)當(dāng)前請(qǐng)求的用戶,獲取到所有權(quán)限,在某一個(gè) DOM 上簡(jiǎn)單隨意的寫上一句判斷代碼,將我們?cè)谥虚g件中匹配 handler 的過(guò)程放到模版渲染的過(guò)程,這樣將沒有權(quán)限的條目過(guò)濾掉,還用戶一個(gè)清靜的世界,同樣可以避免點(diǎn)到不該點(diǎn)的東西。

{% if user.permissions.can_modify_xxx %}
修改xxx
{% endif %}

如果是在不用模版引擎的情況下,我們就需要在頁(yè)面在瀏覽器渲染的時(shí)候,加一個(gè) ajax 請(qǐng)求加載到用戶的權(quán)限列表,用js后期去掩蓋掉不該看到的東西。

前端組件化整理

這樣極大程度的提高了用戶體驗(yàn),但是回顧一下我們的做法,編寫一個(gè)新的功能,處理掉權(quán)限所有關(guān)系配置之后,需要根據(jù)這個(gè) module function 字符串在頁(yè)面上所有用到的地方寫一句判斷語(yǔ)句,這樣非常麻煩。而且如果想要修改一個(gè)權(quán)限的定義,簡(jiǎn)直是災(zāi)難。為了解決這個(gè)問題,我們不得不借鑒一下組件化的設(shè)計(jì)模式,即模版復(fù)用。用模版引擎的繼承、導(dǎo)入可以實(shí)現(xiàn)這個(gè)目的。當(dāng)然 react 是天生的組件化設(shè)計(jì)理念。我們?cè)谝粋€(gè)最上級(jí)組件初始化的時(shí)候?qū)⒃撚脩艟哂械臋?quán)限列表從服務(wù)器端拉取,存儲(chǔ)本地,然后依次向下流入到各級(jí)子組件中,每個(gè)組件配置一個(gè) id(可以與 module function 字符串一致,也可以做一次映射)當(dāng)組件在權(quán)限列表中找到自己的對(duì)應(yīng)的 id 則進(jìn)行渲染。最終整個(gè)頁(yè)面根據(jù)權(quán)限列表將所有可以顯示的部分全部渲染出來(lái)。

剛才提到的組件id這是前后端限制的關(guān)鍵,后端根據(jù) module function 判斷 handler 處理,前端根據(jù) id 判斷渲染與否,那么這個(gè)配置應(yīng)該是前端寫好組件由后端配置,還是后端提供配置權(quán)限入口,由前端自行配置呢?

前后端分工配合

當(dāng)我們討論開發(fā)模式的時(shí)候,總會(huì)遇到這樣一個(gè)問題:

前后端分離還是不分離

分離時(shí)前端工作量加重,路由、組件加載、部署等都要處理,有時(shí)候項(xiàng)目不是很大,這種分離得不償失,但是好處是前后端各司其職,處理自己的部分,不會(huì)產(chǎn)生不必要的工作量。

不分離的情況就是運(yùn)用模版引擎,前端提供靜態(tài)頁(yè)面,服務(wù)器端渲染,這樣有的時(shí)候在后端處理數(shù)據(jù)的同時(shí)可能將頁(yè)面樣式或者動(dòng)畫效果破壞掉,然后又要兩端反復(fù)修改,好處是開發(fā)簡(jiǎn)單,一些功能簡(jiǎn)單且比較單一,可以直接一并處理。

無(wú)論分離還是不分離,提供一個(gè)配置服務(wù)這個(gè)中間產(chǎn)物是有必要的,分離時(shí)我們可以讓前端在寫好組件后,將自己的組件id配置在系統(tǒng)中,后端按照正常的限制邏輯進(jìn)行。不分離時(shí),直接根據(jù)前端頁(yè)面的編寫的 id 進(jìn)行配置,這部分可以由后端完成。有了這個(gè)公共區(qū)的系統(tǒng),想必大家都是很開心的,又能一起愉快的玩耍(coding)了。現(xiàn)在處理這個(gè)問題的開源項(xiàng)目有很多,比如基于 django admin、flask admin 等流行的后臺(tái)管理項(xiàng)目,就可以很好的搭建這種定制化的公共配置部分。

當(dāng)然,具體的設(shè)計(jì)結(jié)構(gòu)需要根據(jù)系統(tǒng)需求作相應(yīng)的變通,可能有些場(chǎng)景限制粒度無(wú)要求,我們可以不作操作對(duì)象的閉環(huán),如果是權(quán)限嚴(yán)格要求的場(chǎng)景(Mario 遇到的場(chǎng)景)就顯得有必要了。前端限制在追求用戶體驗(yàn)的情況是有必要的,組件化會(huì)將結(jié)構(gòu)理得非常清晰,同時(shí)工作量也有所增加。公共區(qū)的配置模塊就像一個(gè)前后端的樞紐,或者說(shuō)是一個(gè)契約,不僅是在權(quán)限限制上,在所有配合開發(fā)的場(chǎng)景都是有所幫助的。

Mario,豈安研發(fā)工程師
主要負(fù)責(zé)豈安 STALKER 項(xiàng)目的設(shè)計(jì)與研發(fā)工作,python 愛好者,對(duì)于 python 在 web
和自動(dòng)化領(lǐng)域中有所探究。天生對(duì)用戶體驗(yàn)至上的產(chǎn)品有極大的好感。夢(mèng)想是將一切極 low 且繁雜的工作交給計(jì)算機(jī)或優(yōu)雅地提供給他人處理。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/40892.html

相關(guān)文章

  • 【Java EE】從零開始寫項(xiàng)目【總結(jié)】

    摘要:目前該功能并未完善,敬請(qǐng)期待。反正每次都會(huì)有新的東西補(bǔ)充上去一開始我本來(lái)想做的是可以使用微信登陸,也可以使用賬戶郵箱登陸,也可以使用短信登陸的。后來(lái)發(fā)現(xiàn)微信登陸要企業(yè)認(rèn)證,做不了。 從零開發(fā)項(xiàng)目概述 最近這一直在復(fù)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法,也就是前面發(fā)出去的排序算法八大基礎(chǔ)排序總結(jié),Java實(shí)現(xiàn)單向鏈表,棧和隊(duì)列就是這么簡(jiǎn)單,十道簡(jiǎn)單算法題等等... 被虐得不要不要的,即使是非常簡(jiǎn)單有時(shí)候繞半...

    imtianx 評(píng)論0 收藏0
  • 智能合約一種設(shè)計(jì)結(jié)構(gòu)

    摘要:所以,在設(shè)計(jì)時(shí),要了解區(qū)塊鏈相關(guān)知識(shí),這些是出于安全考慮。通過(guò)一個(gè)智能合約能夠管理所有模塊,這個(gè)是不變的,相當(dāng)于一個(gè)不變的點(diǎn),用來(lái)鏈接各個(gè)模塊,保證穩(wěn)定,相當(dāng)于在區(qū)塊鏈上一直會(huì)有一個(gè)穩(wěn)定的地址長(zhǎng)期進(jìn)行服務(wù)。 智能合約的設(shè)計(jì)和傳統(tǒng)的應(yīng)用設(shè)計(jì)有點(diǎn)不同。傳統(tǒng)應(yīng)用一般為了快速迭代是在產(chǎn)品之后考慮安全,但是 DApp 則需要在產(chǎn)品出來(lái)之前就考慮安全問題,它將會(huì)關(guān)系到賬戶資產(chǎn)、用戶數(shù)據(jù)等問題,而且...

    evin2016 評(píng)論0 收藏0
  • 聊聊微服務(wù)集群當(dāng)中自動(dòng)化工具

    摘要:本篇博客主要介紹了自動(dòng)化工具這個(gè)概念,在微服務(wù)集群當(dāng)中的作用,算拋磚引玉,歡迎大家提出自己的見解。而在微服務(wù)中,單個(gè)服務(wù)重新部署的代價(jià)明顯要小的多。 本篇博客主要介紹了自動(dòng)化工具這個(gè)概念,在微服務(wù)集群當(dāng)中的作用,算拋磚引玉,歡迎大家提出自己的見解。 寫在前面 在了解自動(dòng)化工具的概念之前,我們先了解一下微服務(wù)和集群的概念。 什么是微服務(wù) 這個(gè)概念其實(shí)有些廣泛,而我的知識(shí)廣度也有限,我會(huì)盡...

    Hancock_Xu 評(píng)論0 收藏0
  • 后端開發(fā)者從零做一個(gè)移動(dòng)應(yīng)用(后端篇)

    摘要:后端開發(fā)的疑惑后端開發(fā)最常面對(duì)的一個(gè)問題性能高并發(fā)等等。而到了時(shí)代,在方面有了前后端分離概念移動(dòng)后端更是無(wú)力渲染天然前后端分離。 先來(lái)上一張前端頁(yè)面的效果圖(Vue + Vux + Vuex + Vue-Router)。showImg(https://segmentfault.com/img/remote/1460000010207850); 第一次做gif 沒什么經(jīng)驗(yàn),太大了。加載...

    codergarden 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

kel

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<