基于微服务API级权限的技术架构
背景
權(quán)限系統(tǒng)是根據(jù)系統(tǒng)設(shè)置的安全規(guī)則或者安全策略,用戶可以訪問(wèn)而且只能訪問(wèn)自己被授權(quán)的資源。
一般而言,企業(yè)內(nèi)部一套成熟的權(quán)限系統(tǒng),都是基于角色(Role)的訪問(wèn)控制方法(RBAC – Role Based Access Control),即權(quán)限(Permission)與角色相關(guān)聯(lián),用戶(User)通過(guò)成為適當(dāng)角色的成員而得到這些角色的權(quán)限,權(quán)限包含資源(或者與操作組合方式相結(jié)合),最終實(shí)現(xiàn)權(quán)限控制的目的。
一言以蔽之,基于角色的訪問(wèn)控制方法的訪問(wèn)邏輯表達(dá)式為“Who對(duì)What(Which)進(jìn)行How的操作”,它的由內(nèi)到外的邏輯結(jié)構(gòu)為權(quán)限->角色->用戶,即一個(gè)角色對(duì)應(yīng)綁定多個(gè)權(quán)限,一個(gè)用戶對(duì)應(yīng)綁定多個(gè)角色,這也是秦蒼基礎(chǔ)架構(gòu)部對(duì)于公共權(quán)限服務(wù)實(shí)現(xiàn)的基本指導(dǎo)思想。
權(quán)限服務(wù)與基礎(chǔ)架構(gòu)部其他公共服務(wù)的關(guān)系圖一.API權(quán)限定義、入庫(kù)和攔截
對(duì)于API權(quán)限,我們實(shí)行基于注解(Annotation)的掃描入庫(kù)和攔截,不需要業(yè)務(wù)服務(wù)自行在界面上錄入
1、權(quán)限定義
API權(quán)限以每個(gè)接口或者實(shí)現(xiàn)類(lèi)中的方法作為權(quán)限資源,每個(gè)權(quán)限和微服務(wù)名(Service Name)掛鉤。
我們通過(guò)在業(yè)務(wù)服務(wù)的API上添加注解的方式,進(jìn)行權(quán)限定義。基礎(chǔ)架構(gòu)部會(huì)提供一個(gè)權(quán)限組件(Permission Component)Jar給業(yè)務(wù)服務(wù)部門(mén),里面包含了自定義的注解,這樣的實(shí)現(xiàn)方式,對(duì)業(yè)務(wù)服務(wù)的影響非常小,增加權(quán)限機(jī)制只是在代碼層面加幾個(gè)注解而已。具體使用方式如下
對(duì)于一個(gè)普通的接口類(lèi),我們可以這樣定義:
| 1 2 3 4 5 6 7 8 | public interface UserService { boolean addUser(@UserId String userId, User user); boolean deleteUser(@UserId String userId, User user); } | 
對(duì)于通過(guò)Swagger方式暴露出去的API,我們可以這樣定義:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public interface UserService { boolean addUser(@PathParam("userId") @UserId String userId, User user); boolean deleteUser(@PathParam("userId") @UserId String userId, User user); } | 
在上述簡(jiǎn)短的代碼中,我們可以發(fā)現(xiàn)有三個(gè)自定義的注解,@Group、@Permission和@UserId。
- @Permission,即為每個(gè)API(接口方法)定義一個(gè)權(quán)限,要求有name(英文格式),label(中文格式)和description(權(quán)限描述) - @Group,即定義的權(quán)限歸屬哪個(gè)權(quán)限組,考慮到一個(gè)接口中包含很多個(gè)API,接口數(shù)目又比較多,那么我們可以為每個(gè)接口下的所有方法歸為一個(gè)組。業(yè)務(wù)服務(wù)可自行定義權(quán)限組,也可以選擇不定義,那么會(huì)歸屬到默認(rèn)預(yù)定義的權(quán)限組中
 
- l@UserId,即業(yè)務(wù)服務(wù)需要在他們的API上加入用戶ID的參數(shù),當(dāng)AOP切面攔截做權(quán)限驗(yàn)證時(shí)候,用戶ID是需要傳入的必要參數(shù)
2、權(quán)限入庫(kù)和攔截
當(dāng)API權(quán)限定義好以后,我們?cè)跈?quán)限組件里面加入掃描權(quán)限入庫(kù)和攔截的算法。采用Spring AutoProxy自動(dòng)代理的框架來(lái)實(shí)現(xiàn)我們的掃描算法。
2.1 創(chuàng)建PermissionInterceptor.java繼承org.aopalliance.intercept.MethodInterceptor,步驟如下
- 實(shí)現(xiàn)Object invoke(MethodInvocation invocation)方法,獲取注解值
- 根據(jù)不同注解進(jìn)行不同的切面攔截,實(shí)現(xiàn)對(duì)@Group,@Permission和@UserId三個(gè)注解的權(quán)限攔截邏輯
2.2 創(chuàng)建PermissionAutoProxy.java繼承Spring的org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator類(lèi),步驟如下
- 在構(gòu)造方法里設(shè)置好Interceptor通用代理器(即實(shí)現(xiàn)了MethodInterceptor接口的攔截類(lèi)PermissionInterceptor.java)
- shouldProxyTargetClass用來(lái)決定是接口代理,還是類(lèi)代理。在權(quán)限定義的時(shí)候,其實(shí)我們還支持把注解加在實(shí)現(xiàn)類(lèi)上,而不僅僅在接口上,這樣靈活運(yùn)用注解放置的方式-
- getAdvicesAndAdvisorsForBean是最核心的方法,用來(lái)決定哪個(gè)類(lèi)、哪個(gè)方法上的注解要被掃描入庫(kù),也決定哪個(gè)類(lèi)、哪個(gè)方法要被代理。如果我們做的更加通用一點(diǎn),那么可以抽象出三個(gè)方法,供getAdvicesAndAdvisorsForBean調(diào)用
| 1 2 3 4 5 6 7 8 | // 返回?cái)r截類(lèi),攔截類(lèi)必須實(shí)現(xiàn)MethodInterceptor接口,即PermissionInterceptor protected abstract Class<? extends MethodInterceptor> getInterceptorClass(); // 返回接口或者類(lèi)的方法名上的注解,如果接口或者類(lèi)中方法名上存在該注解,即認(rèn)為該接口或者類(lèi)需要被代理 protected abstract Class<? extends Annotation> getMethodAnnotationClass(); // 掃描到接口或者類(lèi)的方法名上的注解后,所要做的處理 protected abstract void methodAnnotationScanned(Class<?> targetClass); | 
2.3 創(chuàng)建PermissionScanListener.java實(shí)現(xiàn)Spring的org.springframework.context.ApplicationListener.ApplicationListener接口,步驟如下
- 在onApplicationEvent(ContextRefreshedEvent event)方法里實(shí)現(xiàn)入庫(kù)代碼
-  在微服務(wù)的Spring容器啟動(dòng)的時(shí)候,將自動(dòng)觸發(fā)權(quán)限數(shù)據(jù)入庫(kù)的事件 通過(guò)上述闡述,我們就實(shí)現(xiàn)了權(quán)限的掃描入庫(kù)和攔截 
二、API權(quán)限所對(duì)應(yīng)的角色(Role)管理
角色是一組API權(quán)限的匯總,每個(gè)角色也將和微服務(wù)名掛鉤。角色組的作用是為了匯總和管理眾多的角色
角色管理需要人工在界面上進(jìn)行操作,角色管理分為角色組增刪改查,以及每個(gè)角色組下的角色增刪改查
三、 API權(quán)限所屬的角色和用戶(User)的綁定
權(quán)限不能直接和用戶綁定,必須通過(guò)角色作為中間橋梁進(jìn)行關(guān)聯(lián)。那么我們要實(shí)現(xiàn)
- 角色與權(quán)限的綁定,即一個(gè)角色和多個(gè)權(quán)限的關(guān)聯(lián)
- 用戶與角色的綁定,即一個(gè)用戶和多個(gè)角色的關(guān)聯(lián)
?
用戶和角色的綁定頁(yè)面 </center?
四、權(quán)限系統(tǒng)驗(yàn)證方式
1、API接入的驗(yàn)證方式
通過(guò)遠(yuǎn)程RPC方式的調(diào)用
1.1 掃描接入Permission組件的API Resource
| 1 2 3 4 5 6 7 | com.omniprimeinc.commonservice.permission.annotations.config.Config.class }) public class Config { } | 
1.2 通過(guò)API Resource去調(diào)用RPC接口獲取驗(yàn)證結(jié)果
| 1 2 3 4 5 6 7 8 9 | public interface AuthorizationResource { Boolean authorize(@PathParam("userId") String userId, @PathParam("permissionName") String permissionName, @PathParam("serviceName") String serviceName); } | 
2、Rest調(diào)用的驗(yàn)證方式
http://host:port/authorization/authorize/{userId}/{permissionName}/{serviceName}
通過(guò)User ID、Permission Name(權(quán)限名,映射于對(duì)應(yīng)的方法名)、Service Name(應(yīng)用名)來(lái)判斷是否被授權(quán),返回結(jié)果是true或者false
五、權(quán)限服務(wù)和用戶服務(wù)的整合
用戶服務(wù)即整合了Ldap系統(tǒng)的用戶和橋接業(yè)務(wù)用戶系統(tǒng)
權(quán)限服務(wù)接入用戶服務(wù)后,可以在權(quán)限授權(quán)頁(yè)面上選取相應(yīng)的用戶進(jìn)行權(quán)限授權(quán)
六、權(quán)限服務(wù)的安全控制
未來(lái)規(guī)劃,服務(wù)之間的調(diào)用增加如下機(jī)制
- 黑/白IP名單機(jī)制。當(dāng)A服務(wù)調(diào)用B服務(wù)的時(shí)候,B服務(wù)會(huì)實(shí)現(xiàn)維護(hù)一個(gè)黑/白IP列表,表示B服務(wù)只允許在某個(gè)IP網(wǎng)段的A服務(wù)才能有權(quán)限調(diào)用B服務(wù)
- 服務(wù)間約定的SecretKey。當(dāng)A服務(wù)調(diào)用B服務(wù)的時(shí)候,兩個(gè)服務(wù)之間實(shí)現(xiàn)實(shí)現(xiàn)約定API訪問(wèn)密鑰,此密鑰不能輕易泄密。這樣就規(guī)避了B服務(wù)被模擬Rest請(qǐng)求調(diào)用(例如通過(guò)PostMan調(diào)用)
- 服務(wù)的API簽名。當(dāng)A服務(wù)調(diào)用B服務(wù)的時(shí)候,A服務(wù)需要獲得正確的B服務(wù)API的簽名,才有權(quán)限去調(diào)用
http://blog.springcloud.cn/sc/mfw-jq/
?
總結(jié)
以上是生活随笔為你收集整理的基于微服务API级权限的技术架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: Android Gallery和Imag
- 下一篇: c#后台alert出来变乱码问题解决
