insp4j輕量級權限框架
insp4j輕量級權限框架
簡介
- insp4j為inspector的縮寫,中文含義檢查員。
- 基于Spring-EL、AOP,更加靈活易用的權限控制框架,支持權限分組,可用于一套系統(tǒng)多種權限隔離校驗,使用簡單、易于擴展,支持Servlet、Reactive。
- 參考了SpringSecurity、Expression的設計,定制擴展靈活。
需求背景
一個大的項目里會存在各種子業(yè)務系統(tǒng),比如xx營銷平臺,提供給B端商戶使用,其中包含的子業(yè)務系統(tǒng)有:
商城系統(tǒng)(多門店)、倉庫系統(tǒng)(多倉庫)、運營系統(tǒng)(多部門),系統(tǒng)交給不同的人員進行維護管理,這里統(tǒng)稱操作員。
每個操作員能操作的功能,操作的門店/倉庫/部門都是不一樣的,甚至是不同的用戶體系,不同的粗細粒度,
一般我們每個子業(yè)務系統(tǒng)會給不同的開發(fā)小組開發(fā),如果沒有設計統(tǒng)一的權限處理方案,各個小組會各自實現(xiàn)自己所負責的業(yè)務系統(tǒng)權限,很難管理。
insp4j就是抽象了一個group,把每個不同的子系統(tǒng)的權限設計區(qū)分隔離,不同的group,不同的用戶、操作權限、數(shù)據(jù)權限,這些信息統(tǒng)一封裝在InspAuthentication,需要業(yè)務系統(tǒng)來構造。
insp4j沒有實現(xiàn)用戶認證、授權,更沒涉及到數(shù)據(jù)庫層面上的數(shù)據(jù)范圍過濾,只對業(yè)務系統(tǒng)構造的InspAuthentication、@Insp注解上定義的權限標識基于AOP實現(xiàn)攔截校驗,是輕量級的權限控制實現(xiàn)。
快速開始
- 導包
<!-- Servlet ->
<dependency>
<groupId>cn.is4j.insp</groupId>
<artifactId>insp4j-web</artifactId>
<version>${latest.version}</version>
</dependency>
<!-- Reactive ->
<dependency>
<groupId>cn.is4j.insp</groupId>
<artifactId>insp4j-reactive</artifactId>
<version>${latest.version}</version>
</dependency>
- 配置
/** * 實現(xiàn)接口cn.is4j.insp.web.service.InspWebAuthenticationService返回認證用戶的權限 并交由spring ioc管理 */ @Component public class InspWebAuthenticationServiceImpl implements InspWebAuthenticationService { @Autowired private DeptService deptService; @Autowired private MerchantService merchantService; /** * 建議走緩存 每次攔截都會進入該方法 這里只是演示 */ @Override public InspAuthentication loadAuthentication(HttpServletRequest httpServletRequest, InspMetadataSource metadataSource) { // groupName可以用來做用戶/權限隔離 // 如系統(tǒng)用戶在sys_user表,權限在sys_authorities表,一般用戶(商戶)在biz_merchant表,權限在biz_merchant_authorities表 if("system".equals(metadataSource.getGroupName())){ String userId = SecurityUtil.getUserId(); List<String> funcAuthorities = SecurityUtil.getUser().getAuthorities(); List<String> dataAuthorities = deptService.listDeptId(); return new InspAuthentication(userId, funcAuthorities, dataAuthorities); } if("merchant".equals(metadataSource.getGroupName())){ String userId = merchantService.getIdByToken(httpServletRequest.getHeader("token")); List<String> funcAuthorities = merchantService.listFuncAuthorities(userId); List<String> dataAuthorities = merchantService.listDataAuthorities(userId); return new InspAuthentication(userId, funcAuthorities, dataAuthorities); } throw new RuntimeException("error groupName"); } }
- 使用
@RestController @RequestMapping("/dept") public class DeptController { //操作權限 @Insp("hasFunc('dept:list')") @GetMapping("/list") public R<?> list() { return ok(); } // 操作權限加數(shù)據(jù)權限 有沒有操作該id的權限 // 支持Spring-EL表達式 @Insp(value = "hasFuncData('dept:update',#id)") @GetMapping("/updateById") public R<?> updateById(@RequestParam Long id) { return ok(); } // 權限分組 業(yè)務系統(tǒng)/運營系統(tǒng) 可能用戶賬號體系不一樣,權限體系也是分開設計的,就需要用到groupName來實現(xiàn)分組 // 一個分組可以單獨一套用戶/權限 @Insp(value = "hasFuncData('dept:delete',#id)", groupName = "system") @GetMapping("/deleteById") public R<?> deleteById(@RequestParam Long id) { return ok(); } }
-
異常
沒有權限時默認異常,可定制
{"code":403,"message":"deny of access"}
計劃
- 系統(tǒng)與系統(tǒng)(微服務)之間的調(diào)用權限
- 用戶的認證與授權?OAuth?.待定
- Spring-EL method IDE識別,點擊跳轉直接跳轉到目標實現(xiàn)?.暫時還沒研究出來(inject language or reference)不太理想
ps
這種基于AOP對注解上的權限標識做攔截是很簡單的,相信大家都會,目前提供的功能比較簡單,不喜勿噴
當下主要是解決我們項目里各種系統(tǒng)權限控制不統(tǒng)一,每個子系統(tǒng)不同小組在開發(fā),各自做各自的,增加一個子系統(tǒng)就要做一套權限,沒有統(tǒng)一模式。
開源協(xié)議
This project is licensed under the Apache-2.0 License - see the LICENSE.md file for details
