一個(gè)開(kāi)箱即用的高效認(rèn)證鑒權(quán)框架,專注于restful api的認(rèn)證鑒權(quán)動(dòng)態(tài)保護(hù)
作者:tomsun28
來(lái)源:SegmentFault 思否
寫(xiě)在開(kāi)頭
看了看這個(gè)專欄的最近一篇文章已經(jīng)是兩年前了,時(shí)間過(guò)得好快。應(yīng)該是出學(xué)校后時(shí)間就很快了。兩年前因?yàn)橛胹hiro后,自己就按著想法開(kāi)始做一個(gè)認(rèn)證鑒權(quán)框架 - sureness,想它是針對(duì)restful api的,它是易用的,它是沒(méi)有框架綁定的。就按著這些想法斷斷續(xù)續(xù)的寫(xiě)了兩年,中間陸陸續(xù)續(xù)在maven庫(kù)發(fā)了10個(gè)版本,線上環(huán)境的驗(yàn)證。開(kāi)始在這個(gè)專欄寫(xiě)起來(lái),希望有人關(guān)注和使用sureness - https://su.usthe.com
sureness - 面向restful api的認(rèn)證鑒權(quán)
A simple and efficient open-source jvm security framework that focus on the protection of restful api.
若主頁(yè)usthe.com/sureness?訪問(wèn)不了,請(qǐng)使用備用網(wǎng)站:?su.usthe.com
Background
現(xiàn)在很多網(wǎng)站都進(jìn)行了前后端分離,后端提供rest api,前端調(diào)用接口獲取數(shù)據(jù)渲染。這種架構(gòu)下如何保護(hù)好后端所提供的rest api使得更加重視。api的保護(hù)可以認(rèn)為:認(rèn)證-請(qǐng)求攜帶的認(rèn)證信息是否校驗(yàn)通過(guò),鑒權(quán)-認(rèn)證通過(guò)的用戶擁有指定api的權(quán)限才能訪問(wèn)此api。然而不僅于此,什么樣的認(rèn)證策略, jwt, basic,digest,oauth還是多支持, 權(quán)限配置是寫(xiě)死代碼還是動(dòng)態(tài)配置,我想動(dòng)態(tài)賦權(quán)怎么辦,云原生越來(lái)越火用的框架是quarkus等新秀不是spring生態(tài)咋弄,http實(shí)現(xiàn)不是servlet而是jax-rs規(guī)范咋整, to be or not to be, this is a question.
目前java主流的權(quán)限框架有shiro,spring security, 下面對(duì)于它們的探討都是個(gè)人之見(jiàn),接受糾正
shiro對(duì)于restful api原生支持不太友好,需要改寫(xiě)一些代碼,2年前一個(gè)項(xiàng)目?booshiro?就是改造shiro,使其在過(guò)濾鏈就能匹配不同的rest請(qǐng)求進(jìn)行權(quán)限校驗(yàn),之后給shiro commit幾次pr,fix其在過(guò)濾鏈匹配時(shí)的危險(xiǎn)漏洞,總的來(lái)說(shuō)shiro很強(qiáng)大但其起源并非面向web,對(duì)restful不是很友好
spring security很強(qiáng)大,與spring深度集成,離開(kāi)spring,比如javalin和之前用過(guò)的osgi框架karaf就用不了了
如果不用注解配置,它們都會(huì)在鏈?zhǔn)狡ヅ溥@塊,用請(qǐng)求的url和配置的鏈一個(gè)一個(gè)ant匹配(匹配過(guò)程中會(huì)有緩存等提高性能),但匹配的鏈過(guò)多時(shí)還是比較耗性能(根據(jù)算法時(shí)間復(fù)雜度判斷,暫未測(cè)試驗(yàn)證)
我們希望能解決這些,提供一個(gè)針對(duì)restful api,無(wú)框架依賴,可以動(dòng)態(tài)修改權(quán)限,多認(rèn)證策略,更快速度,易用的認(rèn)證鑒權(quán)框架
Introduction
sureness?是我們?cè)谑褂?java?權(quán)限框架?shiro?之后,吸取其良好設(shè)計(jì)加上一些想法實(shí)現(xiàn)的全新認(rèn)證鑒權(quán)項(xiàng)目
面對(duì)?restful api?的認(rèn)證鑒權(quán),基于?rbac?(用戶-角色-資源)主要關(guān)注于對(duì)?restful api?的安全保護(hù)
無(wú)特定框架依賴(本質(zhì)就是過(guò)濾器處攔截判斷,已有springboot,quarkus,javalin,ktor等demo)
支持動(dòng)態(tài)修改權(quán)限配置(動(dòng)態(tài)修改哪些api需要被認(rèn)證,可以被誰(shuí)訪問(wèn))
支持主流http容器 servlet 和 jax-rs
支持多種認(rèn)證策略,?jwt, basic auth?... 可擴(kuò)展自定義支持的認(rèn)證方式
基于改進(jìn)的字典匹配樹(shù)擁有的高性能
良好的擴(kuò)展接口, demo和文檔
sureness的低配置,易擴(kuò)展,不耦合其他框架,能使開(kāi)發(fā)者對(duì)自己的項(xiàng)目多場(chǎng)景快速安全的進(jìn)行保護(hù)
Framework Sample Support
spring?sample-bootstrap springboot?sample-tom quarkus?sample-quarkus javalin?sample-javalin ktor?sample-ktor spring webflux?sample-spring-webflux more samples todo
快速開(kāi)始
使用前一些約定
sureness盡量簡(jiǎn)潔,基于rbac,只有(角色-資源)的映射,沒(méi)有(權(quán)限)動(dòng)作映射,即 用戶-角色-資源 我們將restful api請(qǐng)求視作一個(gè)資源,資源格式為:?requestUri===httpMethod?即請(qǐng)求的路徑加上其請(qǐng)求方式(post,get,put,delete...) 作為一個(gè)整體被視作一個(gè)資源?eg: /api/v2/book===get?get方式請(qǐng)求/api/v2/book接口數(shù)據(jù) 角色資源映射: 用戶所屬角色--角色擁有資源--用戶擁有資源(用戶就能訪問(wèn)此api)
項(xiàng)目中加入sureness
項(xiàng)目使用maven構(gòu)建,加入maven坐標(biāo)
com.usthe.sureness sureness-core 0.1
項(xiàng)目使用gradle構(gòu)建,gradle坐標(biāo)
compile group: 'com.usthe.sureness', name: 'sureness-core', version: '0.1'
項(xiàng)目為普通工程,加入sureness-core.jar依賴
在 mvnrepository 下載jar?https://mvnrepository.com/artifact/com.usthe.sureness/sureness-core
添加攔截所有請(qǐng)求的過(guò)濾器入口
入口攔截器器實(shí)現(xiàn)一般可以是?filter or spring interceptor?在攔截器加入sureness的安全過(guò)濾器,如下:
入口,一般放在攔截所有請(qǐng)求的filter:
SurenessSecurityManager.getInstance().checkIn(servletRequest)實(shí)現(xiàn)相關(guān)異常處理
sureness使用異常處理流程,我們需要對(duì)checkIn拋出的異常做自定義處理,
安全過(guò)濾器,認(rèn)證鑒權(quán)成功直接通過(guò),失敗拋出特定異常,捕獲異常,如下:
try {SubjectSum subject = SurenessSecurityManager.getInstance().checkIn(servletRequest); } catch (ProcessorNotFoundException | UnknownAccountException | UnsupportedSubjectException e4) {// 賬戶創(chuàng)建相關(guān)異常} catch (DisabledAccountException | ExcessiveAttemptsException e2 ) {// 賬戶禁用相關(guān)異常} catch (IncorrectCredentialsException | ExpiredCredentialsException e3) { // 認(rèn)證失敗相關(guān)異常} catch (UnauthorizedException e5) {// 鑒權(quán)失敗相關(guān)異常} catch (RuntimeException e) {// 其他自定義異常}
加載配置數(shù)據(jù)
sureness認(rèn)證鑒權(quán),當(dāng)然也需要我們配置自己的配置數(shù)據(jù) - 賬戶數(shù)據(jù),角色權(quán)限數(shù)據(jù)等 這些配置數(shù)據(jù)可能來(lái)自文本,關(guān)系數(shù)據(jù)庫(kù),非關(guān)系數(shù)據(jù)庫(kù) 我們提供了配置數(shù)據(jù)接口SurenessAccountProvider,?PathTreeProvider, 用戶可以實(shí)現(xiàn)此接口實(shí)現(xiàn)自定義配置數(shù)據(jù)源 當(dāng)前我們也提供默認(rèn)文本形式的配置數(shù)據(jù)實(shí)現(xiàn)?DocumentResourceDefaultProvider, 用戶可以配置sureness.yml來(lái)配置數(shù)據(jù) 默認(rèn)文本數(shù)據(jù)源sureness.yml配置詳見(jiàn)文檔?默認(rèn)數(shù)據(jù)源
我們提供了使用代碼DEMO:默認(rèn)文本數(shù)據(jù)源具體實(shí)現(xiàn),請(qǐng)參考使用sureness10分鐘搭建權(quán)限項(xiàng)目--sample-bootstrap
若權(quán)限配置數(shù)據(jù)來(lái)自數(shù)據(jù)庫(kù),請(qǐng)參考使用sureness30分鐘搭建權(quán)限項(xiàng)目--sample-tom
HAVE FUN
非常歡迎參與項(xiàng)目使用和貢獻(xiàn),幫助sureness走得更遠(yuǎn)更好。對(duì)項(xiàng)目代碼有疑問(wèn)或者建議請(qǐng)直接聯(lián)系 @tomsun28

