有贊權限系統

文 | 毛成光、馬純潔 on 零售php

有贊做爲一個商家服務公司,經過產品和服務,幫助互聯網時代的生意人成功。在新零售的浪潮下,有贊零售爲商家提供不一樣規模的門店和網店經營解決方案,幫助零售商家們快速進入新零售時代。與傳統網上商城場景不一樣,零售面對着全新的業務場景和難題,一家運轉成熟的新零售店鋪,一般須要包括老闆、店長、客服、收銀員、覈銷員、倉管、財務等十餘個不一樣能力的角色分工、搭配。擺在零售商家們眼前的一大難題是,如何優雅的管理各個員工,自由分配角色,無痛又潤滑地解決員工角色管理問題。在充分分析零售行業業務場景,員工角色管理方案的不斷探索討論後,權限系統 SAM(Security Access Manager)應運而生,SAM 是有贊零售在員工角色權限管理道路上探索的里程碑,支持着零售 PC、App 和 Pad 產品的權限業務,任何一家使用了有贊零售的零售店均可以經過 SAM 權限系統提供的服務來靈活的給店裏員工靈活分配角色,責任到人,以此提升店鋪運轉效率;支撐零售業務的同時,抽象出了一套權限管理框架,對其餘業務線產品(微商城)進行一樣支持。node

在介紹 SAM 系統以前,首先以幾個案例來理解權限系統的概念和設計。python

計算機世界中的許多事物是現實世界的一個陰影,現實中所見的許多模式/概念在計算機世界裏都能找到。曾記否,QQ 裏隱身對她可見,怕她看不見,下線又上線,卻依舊被視而不見;曾記否,親密無間的戀人們,分手後變成了最熟悉的陌生人,悲痛傷心之餘,微信、電話、 QQ 拉黑。這些案例,都是計算機權限系統對現實世界的一個映射,你對女神隱身可見,其實是賦予了她能夠看到你的隱身狀態(真實狀態)的權限,固然你也賦予了人家傷害你的權限;戀人們把對方拉到了黑名單用戶組,這樣一來,他們就看不見相互動態,成爲最熟悉的陌生人;今後,從你的全世界路過。web

RBAC

上面例子,咱們能夠抽象出這樣的模式:「 Who 對 What(Which)進行 How 的操做」 。例如,戀人們的例子,在你拉黑對方後,在朋友圈中你(Who)將看不到(How)對方的消息(What)。這是一個經典的 RBAC(基於角色的權限訪問控制)權限模型。RBAC 認爲權限受權其實是 Who、What、How 的問題。在 RBAC 模型中,Who、What、How 構成了訪問權限三元組,也就是「Who(權限的擁用者或主體)對 What(Which)(權限針對的對象或資源)進行 How(具體的權限)的操做」。數據庫

RBAC 模型引入了「角色」的概念。所謂「角色」就是一個或一羣用戶在系統中可執行操做的集合,它是一個用戶的集合,又是一個受權許可的集合。經過將角色指派給用戶,爲角色賦予權限的方式,使用戶和權限經過角色間接相聯繫。RBAC 基本模型如圖所示:
sam後端

在 RBAC 中,用戶與角色之間、角色與權限之間都是多對多的關係。會話是一個用戶對多個角色的映射,此時的用戶權限能夠爲激活角色權限的並集。RBAC 對資源受權管理過程分爲兩個部分,首先實現訪問權限與角色相關聯,而後再實現角色與用戶相關聯,從而實現了用戶與訪問權限的邏輯分離。api

權限系統 SAM

SAM 權限系統模型設計

RBAC 模型不一樣於強制存取控制以及自由選定存取控制直接賦予使用者權限,是將權限賦予角色。在 RBAC 中,權限與角色相關聯,用戶經過成爲適當角色成員而獲得這些角色的權限,角色可依新的需求和系統的合併而賦予新的權限,而權限也可根據須要而從某角色中回收。RBAC 相對於傳統訪問控制更爲中性且更具靈活性的存取控制技術。從一家零售店鋪員工角色管理角度看,設置角色是爲了完成各類工做而創造,員工則根據它的責任和資格來被指派相應的角色,員工應該能夠很容易地從一個角色被指派到另外一個角色。所以,零售選擇了基於 RBAC 模型來實現權限系統解決商家們管理員工角色問題。緩存

依據 RBAC 模型思想,SAM 權限系統業務模型設計爲員工管理和權限管理兩部分,員工管理主要指管理員工以及爲員工指派角色,權限管理主要指管理菜單、頁面、按鈕、API 等資源,經過定義最基本的業務功能點做爲權限點,實現管理角色對資源主體的請求,構成「用戶-角色-權限-資源」的受權模型。
sam安全

下面是 SAM 權限系統模型中的一些通用語言:微信

  • 員工:角色的載體,權限的實行者
  • 角色:角色是權限集進一步映射。業務系統可動態管理角色,各業務爲方便用戶使用可提供給默認角色列表,知足不一樣的員工權限
  • 權限點:全局惟一的用來表示某一個功能點對應的權限的狀態
  • 功能點:邏輯上定義的用來描述系統資源的最小基本單位,每個功能點都對應惟一一個權限點
  • 功能集(權限集):即功能點的集合,有一組功能點按照特定格式進行組合
  • API:請求系統資源的通道和動做,擁有功能集屬性
  • 菜單:將系統資源組織後展現給請求者的入口,擁有功能集屬性
  • 頁面:被當作一種特殊的菜單,擁有 URL 屬性
  • 按鈕:頁面中更細粒度的資源入口,被看成一種特殊的菜單

SAM權限系統模型的實現

在傳統的 RBAC 模型中,一般經過一張關係表來保存角色與權限集的對應關係,實現權限與角色相關聯。能夠預見的是,隨着零售業務的不斷髮展會積累下不可勝數的功能點,致使關聯表的數據極難維護和使用。SAM 權限系統利用進制轉換的策略解決了這個問題 ,同時提升了存儲效率以及權限斷定效率。一個基本類型爲 Long 的十進制數字,它也能夠看作是由 64 位 0 或 1 組成的二進制。在 SAM 系統模型設計中,每個功能點定義爲一個權限點,該權限點由 idx 和 pos 兩個屬性確保是全局惟一的權限點。idx 表示第幾個 Long 型空間,pos 表示 Long 型對應的二進制數中所處的位置,64 位長度便可表明 64 個不一樣能功能點。當 64 位滿時沒法再容放更多的功能點,這時 idx 屬性會自增,從新申請一個 Long 型空間。如此一個 64 位的 Long 數字,經過 0 或 1 的組合,便可表示最多對 64 個不一樣的功能點所擁有權限的狀態描述。

例如:權限集{1}表示擁有 idx=0, pos=0 對應功能點的權限,權限集{-1,1}表示擁有idx=0,pos∈[0,1,2,..,63]與 idx=1,pos=0 對應功能點的權限。

SAM 權限系統將資源與所表明的功能點的關聯關係經過進制的方式管理起來,採用計算機進制的思想,抽象出功能集換算公式來完成資源與二進制之間的映射,以及角色與二進制的映射。

權限集換算公式:
{(idx0,pos0),(idx0,pos1)…(idxN,posM)} => {Long0,Long1…LongN}

SAM 權限系統一樣經過進制思想實現「 Who 對 What 進行了 How 的操做」,角色請求某個資源(菜單/API)時,經過權限校驗計算公式——進制按位「與」運算操做的思想(見下)得出該角色是否擁有訪問資源的權限。採用進制來實現運算,權限斷定的效率會變得更加的高效。例如,一個倉管在點擊一個商品庫存菜單時,背後的權限校驗計算公式,實際上是將角色的權限集與資源的權限集進行按位與計算,任意一對序號爲 idx 的 Long 算得不爲 0,即兩集合有公共的功能集,認爲該角色擁有對資源訪問的權限。

權限校驗計算公式:
{Long0,Long1…LongN} & {Long0,Long1…LongM}

SAM 權限系統模型的實現遵循 RBAC 模型中的最小權限原則,責任分離原則和數據抽象原則三大原則,經過最小權限原則能夠將角色配置成其完成任務所須要的最小的功能集;有了責任分離原則能夠經過調用相互獨立互斥的角色來共同完成敏感的任務而體現,好比要求一個倉管和商品管理員共同參與一個商品。數據抽象則能夠經過權限的抽象來體現,如倉管操做商品發貨,庫存管理等抽象權限,而不用操做系統提供的典型的讀、寫、執行權限。

SAM 權限系統架構

零售經過 PC、App 和 Pad 來知足不一樣商家的終端需求,所以 SAM 權限系統須要知足零售不一樣客戶端權限業務場景,同時也要支持微商城產品權限業務。SAM 權限系統採用微服務的方式對外提供服務,採用分佈式分層架構實現,主要包括客戶端和服務端兩部分,客戶端以輕量的方式嵌入在業務系統,提供給不一樣業務系統實現角色訪問資源的控制;服務端經過提供 Dubbo 服務,Nova 服務跟客戶端進行交互。服務端主要對員工,菜單,角色,API,功能點進行數據管理。SAM 做爲基礎服務,天天的請求量巨大,經過 Redis 緩存來解決性能問題,選用 Druid 做爲數據庫鏈接池,管理着數據庫的鏈接以及釋放。同時,經過對接天網監控平臺來觀察系統運行狀態,提升系統的穩定性。
sam
有贊零售系統基於 SAM 實現的角色對於資源的訪問控制主要是 API 校驗和菜單渲染,任何一家零售店登入有贊零售系統後,點擊頁面中的某一個菜單或者頁面元素(按鈕,連接…),都會進行菜單渲染以及 API 接口的校驗。因爲兩部分調用量巨大,同時不一樣的客戶端請求量不一樣,防止相互之間干擾,所以將菜單渲染,API校驗等能力在不一樣的客戶端中各自實現。

菜單渲染

SAM 經過客戶端的方式進行接入,菜單渲染在客戶端一側進行。目前 SAM 已經提供了 php/node js 兩套客戶端,供 web 層進行接入和渲染。
菜單渲染的過程能夠分爲三點:

1、結點定位

按照系統功能的劃分,菜單一般以一棵樹的形式進行展示。以零售 PC 後臺爲例,全部在頁面中展現的元素,都認爲是一種菜單,這樣的菜單元素包括:菜單、頁面、按鈕。在後臺訪問時,用戶停留的菜單一般是頁面,頁面有一個全局惟一的屬性:URL,往上:能夠經過父菜單找到根結點,往下,頁面下可能包含一些子菜單——按鈕。所以 SAM 只須要根據當前請求的 URL,便可在後臺菜單樹中定位到惟一的頁面菜單,同時得到該菜單的結點路徑以及擁有的按鈕。

2、權限計算

咱們已經得到了用戶的角色權限和完整的菜單樹,根據每一個菜單結點的權限集,能夠計算出當前用戶對結點的訪問權。根據計算結果,客戶端對菜單能夠進行區分渲染,好比:用戶經過拼 URL 訪問一個無權限頁面時會提示非法,無權限訪問的菜單和按鈕會自動置灰不可點擊。

3、屬性傳遞

默認菜單不具有 URL 屬性。菜單的 URL 屬性經過子菜單的 URL 傳遞生成,SAM 會選擇第一個有權限的子菜單的 URL 做爲父結點的屬性,並逐級傳遞到一級菜單。

sam

API 權限校驗

零售系統中除了菜單外,API 是另外一種被請求的資源類型。API 校驗是除了菜單渲染外另外一道權限控制的保障。經過卡門( API 網關)的 API 請求轉發到具體業務系統時,嵌入在業務系統中的 SAM API 校驗客戶端會首先經過上面的權限校驗計算公式對該角色是否具備權限訪問這個 API 進行斷定,若權限校驗經過則執行後面業務邏輯。

具體流程以下圖所示
sam

API 權限校驗的僞代碼實現:

#權限不經過錯誤碼提示信息
AUTHPERM_ERROR(231000401,"您沒有權限執行該操做!")
# 織入點
@Before("@annotation(com.youzan.sam.common.Auth)")
# 切面處理方法
def handle(JoinPoint pjp):
    # 能夠啓動時或者運行時控制該開關是否對API進行權限校驗
    if(!enable):
         return
    # 權限校驗結果包裝對象
    def pass=checkPermission()
    # 權限校驗執行成功
    if (pass.isSuccess()):
       # 權限校驗經過
       if(pass.getData().get("isSuccess")):
         return
       # 權限校驗不經過
       else:
         throw new BusinessException(AUTHPERM_ERROR.getCode,AUTHPERM_ERROR.getMessage());
    # 權限校驗執行失敗
    else:
       throw BusinessException(pass.getCode(), pass.getMessage())

# 權限校驗方法
def checkPermission():
    # 判斷是否須要走權限校驗,對於某些內部調用能夠直接跳過
    {...}
    # 獲取卡門(API網關)隱式參數,運用了dubbo的隱式傳參的能力
    def kdt_id=RpcContext.getContext().getAttachment(Constants.KDT_ID_KEY)
    def admin_id=RpcContext.getContext().getAttachment(Constants.ADMIN_ID_KEY)
    def service = RpcContext.getContext().getAttachment(Constants.SERVICE_KEY)
    def method = RpcContext.getContext().getAttachment(Constants.METHOD_KEY)
    def version = RpcContext.getContext().getAttachment(Constants.VERSION_KEY)
    # 上述參數的校驗
    {...}
    # 經過StaffPermServiceProxy獲取角色的權限集
    def staffPerm=StaffPermServiceProxy.getStaffPerms(adminId, kdtId)
    # 經過APIPermServiceProxy獲取API的權限集
    def apiPerm=APIPermServiceProxy.getServicePerms(service, version, method)
    # 運用權限校驗計算公式斷定該角色是否能夠訪問此API
    {...}
    # 返回結果
    return pass

API 權限校驗流程能夠總結以下:

  1. 業務方在對應須要權限校驗的 API 上標註 @Auth 註解,Spring 框架會在初始化建立業務 bean 的時候,掃描該 bean 是否有 @Auth 註解標註的方法,對於有 @Auth 註解標註的,會建立代理類,而後會將該權限切面織入到代理類中;
  2. 業務調用有 @Auth 註解標註的方法時,會執行該權限校驗切面邏輯,首先檢查權限校驗開關,判斷是否須要權限校驗,該開關能夠在運行時動態設置;
  3. 若是須要,再調用 AuthService 的權限校驗方法,AuthService 會根據店鋪 ID 與用戶 ID 從 SAM 服務端獲取員工角色權限信息,根據卡門(API 網關)隱式參數中 service,method,version 去 SAM 服務端獲取對應 API 權限(相對於在對應 API 上直接標註權限點,這種方式更加的靈活,並且能夠隨着業務 API 版本的升級,進行很方便的升級,同時結合卡門( API 網關)能夠對 API 進行分流,不一樣的商家能夠對應不一樣 API 的權限校驗。
  4. 在獲取到角色權限集和 API 權限集後,基於上面的角色與權限校驗邏輯進行權限校驗。校驗經過,則正式發起 API 請求。校驗不過,則提示無權限。

SAM權限系統抽象模型

產品在分析完需求後,將需求交由開發去完成。SAM 權限系統支撐着零售業務的同時,也支撐着微商城業務。 零售各個模塊就有不一樣的產品支撐着,爲了更好的知足服務商家的需求,以及方便產品們的分析。SAM 權限系統能夠抽象成以下模型,商家和產品能夠從各自不一樣的視角,去對接 SAM 權限系統。例如,下圖所示商家想要一個運營的角色須要有新建商品,以及查看訂單的能力,同時須要一個收銀員只有查看訂單的能力。產品從本身的設計角度分析,對應的就是商品管理,訂單管理的模塊,對應的模塊下有對應的商品,訂單菜單,最後將角色的權限體如今頁面元素和 API 上,例如新建商品的按鈕,以及查看訂單的按鈕會呈現不一樣的渲染樣式;按鈕觸發對應的是與後端交互的不一樣 API,不一樣的角色具備 API 的不一樣執行能力。
sam
sam

將來展望

自定義角色

在瞭解商家需求後,零售提供了 8 大默認角色來支持單店版的員工角色問題。零售業務錯綜複雜,默認角色不少時候並不能對付全部場景,如今一些自定義角色已經在某些零售店使用。將來自定義角色將全線支持各個商家,定製任意權限的任意角色。

多角色

有些零售商家爲了縮減人力成本,一個員工經常擔任多個角色,所以須要提供一個員工多角色的能力。零售業務已經在使用多角色的能力。

零售中臺的支持

零售中臺是有贊零售的一個旗艦型產品,旨在爲商家提供一個覆蓋線上多渠道線下多門店的全渠道解決方案,並利用數據化運營思路幫助商家拉新獲客、提升復購。其業務形態很是複雜,涉及到多種角色和權限的組合,並且每一個商家可能存在一些個性化需求,如何提供靈活的適配能力是 SAM 系統的一個挑戰。

自定義菜單

過去後臺功能的發佈上線,每每是由發佈系統控制,發佈則功能即刻上線,一旦發現故障立時回滾。SAM 經過菜單管理,能夠實時控制線上的任意菜單、頁面和按鈕的渲染狀態,從容地上下線頁面和功能。

技術改造

SAM 做爲零售以及其餘業務的公共基礎組件,須要打形成一個高可用,高性能,易擴展,可伸縮且安全的系統。隨着業務的不斷接入,經過對系統的不斷改造來支撐業務的不斷髮展。

結語

權限系統目前歸屬有贊零售技術團隊,對外開放權限接入和員工服務化能力。目前團隊業務發展迅速,HC 持續開放中,期待更多有志之士加入搞事情。

圖片描述

相關文章
相關標籤/搜索