《通用型認證與授權最小系統,以較小的代價實現中立開源項目:UniAuth》要點:
本文介紹了通用型認證與授權最小系統,以較小的代價實現中立開源項目:UniAuth,希望對您有用。如果有疑問,可以聯系我們。
五年前,就如很多創業公司剛開始的時候一樣,點融網的主要業務架構在一個被稱為MainApp + Workflow上的應用:MainApp處理投資者的投資、充值、提現等投資端的操作;用Workflow來處理所有的進件、審批、放款、催收等貸款端的操作.當業務體量并不大的時候,世界一切都顯得那么簡單.前面一個包含了MainApp + Workflow的應用,后面一個包羅萬象的數據庫.一切為了快速的迭代和發展!彼時那是一個 App + 一個 DB的時代.
斗轉星移,點融網漸漸從一個小荷才露尖尖角的小松鼠,發展成一個互金領域的強力領軍人物之一.發展到這個階段的公司,很多都會經歷業務的復雜度極具上升,需要通過分拆業務系統來承載更多的業務流量及復雜性.于是很自然的,前邊的應用,從1變成了N.點融的世界開始變得不是那么簡單.我們的工程師面對著 N * App 的場景.每個應用都在做自己的權限控制模塊.因為,似乎每個應用的服務對象都不盡相同.有銷售、有運營、有技術支持、有財務審計等等.
所以,誰/何種角色,對于某些特征資源擁有怎樣的訪問權限?這是縈繞在很多點融工程師心中的一個問題.
兩年前,幾位點融的工程師,被賦予了這樣的使命.以較小的代價實現中立的,脫離于特定業務場景的 認證(authentication) 和 授權(authorization) 功能 – UniAuth.
擺在這些工程師面前的有這樣一些問題:市場上是否有類似的系統可以被使用呢?
UniAuth這種類型的系統,在市場上叫做 IAM (Identity Access Management) .UniAuth既是以做輕量化的IAM為目標. 這方面在美帝做得最好的公司叫做 okta(15年估值15億美金) , ?amazon 的AWS里面也有IAM. 美國的公司, 對于國內有墻, 服務器不穩定的可能性、對中國support不好 這些因素導致我們很難選擇美國的IAM產品, 并且這些服務,本身的資費對于一個處于成長期的公司而言太貴,同時對于互金類公司而言,對于數據/系統的安全性的考量,我們會更傾向于基于框架上的二次開發模式. 縱觀當時市場上輕量級的 IAM 系統, 要么沒有開源滿足點融需求可用的、要么僅存在于精美的PPT當中.
基于成本的考量,當時的點融還沒有相應的預算投入到這些在業務價值中的優先級較小的項目中.
基于定制化需求的考量 自己公司做一個,持續投入資源 在support上形成優勢.UniAuth的目標
基于以上設計原則,我們選擇了CAS + Spring Security的開源組合來作為我們Uniauth框架開發的基礎、設計一套基于mysql的權限模型 將其融入到SpringSecurity中,為點融網的前后端分離進行了定制化,Uniauth雛形就有了.
在這樣的架構下, cas服務器獨立地存在, 擁有了擴展uniauth-server 數據源的可能性,可以同時 從LDAP取得 企業用戶數據, 也允許客戶端以純webservice的形式集成到Uniauth當中. 在authentication、authorization、data level filter的整個鏈條中,每一個鏈條都可以被打斷.
舉例來講,我們來了一個python base的客戶,他只想要做authentication, 那么在上圖中, 只需要通過cas完成authentication拿到用戶的identity, 然后再使用identity去uniauth-server 得到該identity的profile即可滿足其需求,整個流程全部以webservice的形式完成, 與客戶端語言無關.
再舉例來講,數據系統想要數據,直接問uniauth-server的api索取即可.當然默認情況下我們提供了強大的基于SpringSecurity的CAS客戶端,內網Java base的客戶集成起來要相對容易很多.
源代碼模塊化, 比如客戶端(uniauth-server的) 如 業務系統、數據系統 僅依賴common模塊即可訪問uniauth-server的讀接口,并且盡可能少的依賴jar包.客戶端(uniauth-server的) 如 techops、cas 僅依賴share-rw即可訪問 uniauth-server的讀 和 寫 接口.同時 uniauth-server提供的接口是基于jax-rs標準的json 接口, 所以異構系統完全可以自己寫客戶端訪問uniauth-server.
集成系統 集成Uniauth框架圖:
該圖描述了一個以正常形式集成Uniauth系統的java base的集成方的流程.
SSO純API集成流程圖:
Uniauth提供了純API的形式集成Uniauth的系統, 該方式給予了客戶最大化的自由,不想使用我們提供的任何jar包,或者異構系統.集成想要自由,就給它自由, ?而且自由的同時保證了認證機制的安全.
數據庫模型圖(在沒有加上SaaS化之前的版本):
現在的數據庫里面對于User表又擴展了其EAV模型, 增加了SaaS etc..幾個比較重要的點:
為了避免過長的篇幅描述UniAuth中多個樹狀數據結構,以一個網易評論樹來做講解
UniAuth采取了閉包表的數據設計方式:
Comment Table Data:
Comment Path Table Data:
這種設計, comment table本身并不保存 評論與評論之間的關系, 而將該關系用另外一張表(comment_path)保存起來, 理論上講需要O(n2)的空間來存儲關系,但現實中并不會需要這么多.
每根紅線都是comment_path中的一條數據, 線條上的數字為depth.
查詢直接回復4號comment的comment(父查子)
select c.* from comment c join comment_path cp on (c.id = cp.descendant) where cp.ancestor = 4 and depth = 1;
查詢所有回復4號的子comment(父查所有子)
select c.* from comment c join comment_path cp on (c.id = cp.descendant) where cp.ancestor = 4;
–如果你需要保留層級關系, 則將cp中的值也返回即可
查詢所有7號的 父comment(子查所有父)
select c.* from comment c JOIN comment_path cp on (c.id = cp.ancestor) where cp.descendant = 7;
添加一條子回復到 6號comment上(新增)
step a:
insert into comment(value, topic_id, user_id) values(‘(10)我以gin食阼啦’, 1, 2);
— 拿到該句返回的id, 假設為10
step b:
insert into comment_path (ancestor, descendant, depth) select cp.ancestor, 10, cp.depth+1 from comment_path as cp where cp.descendant=6 union all select 10, 10, 0;
— 只要擁有子comment_id為6作為子節點的節點,全都新增一個id為10,depth+1的子節點 并且插入一個10, 10, 0的節點.
從評論鏈中刪除4號comment及其子comment(刪除子或者子樹)
delete a from comment_path a join comment_path b on (a.descendant = b.descendant) where b.ancestor=4;
— 這句話等價于 “delete from comment_path where descendant in (select descendant from comment_path where ancestor = 4);”, 但mysql會報from句子中的表不能用于update
將6號comment的父comment更改為2號(移動子或者子樹)
step a:
delete a from comment_path as a join comment_path as d on a.descendant = d.descendant left join comment_path as x on x.ancestor = d.ancestor and x.descendant = a.ancestor where d.ancestor = 6 and x.ancestor is null;–這樣刪除的原因和需求5一致.
step b:
insert into comment_path (ancestor, descendant, depth) select supertree.ancestor, subtree.descendant, supertree.depth+subtree.depth+1 from comment_path as supertree join comment_path as subtree where subtree.ancestor = 6 and supertree.descendant = 2;
以上6種需求覆蓋了最為常用的幾種情況,解決了基本上UniAuth在閉包表上遇到的所有的問題.
closure table是反模式設計的一種經典設計, 在結構化數據庫里面,SQL可以很輕易高效地 支持對樹的各種各樣的增、刪、改、查、移的需求.這種設計給到UniAuth系統中的數據表設計特點給了很大的支持.
市場上會有一些開源的IAM系統.相較于很多項目在項目前期處于Bug較多的探索時期,UniAuth經過兩年多的點融內部研發,和互金生產環境的檢驗,UniAuth已經是一個成熟的生產環境質量的產品.
相較于市場上一些IAM系統不菲的軟件授權費用/授權使用費用,UniAuth將項目源碼完全開源.并鼓勵更多的極客可以貢獻的代碼,讓很多公共模塊可以投入更少,成效更快.
UniAuth的底層架構實現了SpringSecurity, 并且通過CAS實現Authentication, 因此可以支持包括SPEL在內的所有CAS, SpringSecurity的特性及其拓展.
對于早期的創業公司而言,成本控制永遠是一個中心話題.基于MySQL的數據庫,降低了很大的運營成本.并且,UniAuth的數據庫設計,對于樹狀結構數據的增改,做了大量優化和特定設計.這會在后文提到.
同時支持客戶端和REST API訪問.解決跨域訪問問題.
CAS天生自帶SSO的實現, 為應用的Authentication提供更多的擴展可能性.
隨著點融的發展,點融技術部門也以更加開放的心態回饋社會,將UniAuth項目加入到開源項目社區. https://github.com/dianrong/UniAuth
錢晟龍,UniAuth項目組成員,點融網資深軟件開發工程師,嘗試設計并解決各類軟件開發中遇到的實際問題,喜歡從已有成熟解決方案中找尋輪子,前端、后端、運維、溝通、管理、寫運營稿,哪里重要去哪里, 現主要負責點融網SSO、OAuth2、JWT etc .. 認證授權相關功能.
文章來自微信公眾號:高效開發運維
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4228.html