Light Security基于?JWT?的權(quán)限控制框架
Light Security是一個(gè)基于 jwt 的權(quán)限控制框架,支持與 Spring Boot 配合使用。
特點(diǎn)
優(yōu)點(diǎn)
- 上手快速
- 開箱即用
- 輕量級,代碼精簡,不到500行代碼;
- 功能實(shí)用,市面上安全框架常用能力與套路均已具備:
- 支持
RESTful權(quán)限控制 - 支持靈活的權(quán)限配置(代碼配置方式優(yōu)先級更高)
- 支持基于配置文件的權(quán)限配置
- 支持基于代碼的權(quán)限控制
- 支持基于注解的權(quán)限控制
- 支持
- 設(shè)計(jì)簡單,沒有復(fù)雜概念;
- 基于權(quán)限配置的方式:核心是1個(gè)攔截器
- 基于注解的權(quán)限控制:核心是1個(gè)切面
缺點(diǎn)
- 功能比Spring Security、Apache Shiro弱;
- 只考慮權(quán)限相關(guān)問題
- 不考慮身份認(rèn)證(登錄),意味著登錄邏輯得自己玩;
- 不考慮安全,意味著網(wǎng)絡(luò)攻擊得自己防;
- 目前與Spring MVC強(qiáng)綁定,暫不支持WebFlux或其他框架。
依賴
- Spring MVC:用到Spring MVC的攔截器;
- Spring AOP:如果不用基于注解的權(quán)限控制,則無需該部分依賴;
- jwt:你懂的
快速上手
TIPS
快速上手可詳見項(xiàng)目
light-security-example目錄,內(nèi)附詳細(xì)測試步驟。
基于配置文件的權(quán)限配置
-
加依賴:
<dependency> <groupId>com.itmuch.security</groupId> <artifactId>light-security-spring-boot-starter</artifactId> <version>1.0.1-RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> -
寫配置
light-security: # 權(quán)限規(guī)則配置:表示用{http-method}方法請求的{path}路徑必須具備什么{expression} spec-list: - http-method: ANY path: /login expression: "anon()" - http-method: ANY path: /user expression: "hasAnyRoles('user','admin')" - http-method: GET path: /error expression: "anon()" - http-method: ANY path: /** expression: "hasLogin()" jwt: # jwt sign算法 algorithm: hs512 # jwt secret secret: http-security-secret-modify-mehttp-security-secret-modify # jwt 有效時(shí)間 expiration-in-second: 1209600 -
寫代碼:
@RequestMapping @RestController @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class TestController { private final UserOperator userOperator; private final JwtOperator operator; /** * 演示如何獲取當(dāng)前登錄用戶信息 * - 該路徑需要具備user或admin權(quán)限才可訪問,詳見application.yml * * @return 用戶信息 */ @GetMapping("/user") public User user() { return userOperator.getUser(); } /** * 演示基于注解的權(quán)限控制 * * @return 如果有權(quán)限返回 親,你同時(shí)有user、admin角色.. */ @GetMapping("/annotation-test") @PreAuthorize("hasAllRoles('user','admin')") public String annotationTest() { return "親,你同時(shí)有user、admin角色.."; } /** * 模擬登錄,頒發(fā)token * * @return token字符串 */ @GetMapping("/login") public String loginReturnToken() { User user = User.builder() .id(1) .username("張三") .roles(Arrays.asList("user", "admin")) .build(); return operator.generateToken(user); } }
基于代碼的權(quán)限配置
@Configuration
public class LightSecurityConfigurtion {
@Bean
public SpecRegistry specRegistry() {
return new SpecRegistry()
.add(HttpMethod.GET, "/user", "hasAnyRoles('user')")
.add(HttpMethod.ANY, "/**", "hasLogin()");
}
}
此時(shí),application.yml 中的如下配置可刪除,因?yàn)榇a配置方式優(yōu)先級更高,配置文件方式將會(huì)失效。
light-security:
# 權(quán)限規(guī)則配置:表示用{http-method}方法請求的{path}路徑必須具備什么{expression}
spec-list:
- http-method: ANY
path: /login
expression: "anon()"
- http-method: ANY
path: /user
expression: "hasAnyRoles('user','admin')"
- http-method: GET
path: /error
expression: "anon()"
- http-method: ANY
path: /**
expression: "hasLogin()"
擴(kuò)展點(diǎn)
| 類 | 作用 |
|---|---|
| com.itmuch.lightsecurity.jwt.UserOperator | 提供用戶相關(guān)操作,例如解析token獲得用戶信息等。 |
| com.itmuch.lightsecurity.el.PreAuthorizeExpressionRoot | 提供了表達(dá)式,例如hasAnyRoles('user') 等,如需新能力,只要寫新方法即可 |
| com.itmuch.lightsecurity.annotation.support.PreAuthorizeAspect | 為注解 @PreAuthorize("hasAllRoles('user','admin')")提供支持 |
常見問題
為什么要再造個(gè)輪子?
老是有人問我諸如"微服務(wù)安全怎么管理?"、"Spring Securityxxxx問題你遇到過嗎?"、"能寫個(gè)Spring Cloud Security的系列教程嗎?"、"Shiroxxxx問題你遇到過嗎?"
煩不勝煩,初期積極回復(fù);后來消極回復(fù);再后來懶得回復(fù)。
分析一下,發(fā)現(xiàn)主要原因還是Spring Security、Shiro學(xué)習(xí)曲線較高,特別是Spring Security。所以就想寫個(gè)輕量的框架,能夠快速解決主要矛盾——足夠簡單、能實(shí)現(xiàn)權(quán)限控制。
為什么實(shí)現(xiàn)一個(gè)通用的權(quán)限解決方案?
有考慮實(shí)現(xiàn)一個(gè)通用權(quán)限框架,但那樣會(huì)增加挺多代碼,而且要添加挺多適配邏輯(例如適配Spring MVC、WebFlux等)。
個(gè)人認(rèn)為這在現(xiàn)階段去實(shí)現(xiàn)還不合適,個(gè)人不太喜歡畫餅。既然"通用性"不是目前最主要的矛盾,高效解決問題相對更加重要。那何必花精力去實(shí)現(xiàn)通用性?設(shè)計(jì)上支持往"通用性"遷移即可。
未來如果有需求,我會(huì)做一個(gè)通用版本,并且低版本也可無痛、平滑地遷移。
為什么不考慮身份認(rèn)證(登錄)?
目前市面上大多權(quán)限框架都考慮了"身份認(rèn)證(登錄)" + "權(quán)限管理" 。然而登錄操作在現(xiàn)在這個(gè)時(shí)代,是一個(gè)"五花八門"的操作。例如:
- 手機(jī)號 + 驗(yàn)證碼登錄
- 掃二維碼登錄
- 賬號密碼登錄
- 證書登錄
往往還需還同時(shí)支持多種登錄方式。這挺難去抽象出通用模式,并為典型的登錄方式提供支持。
索性不考慮了——把登錄問題留給使用者自己。用戶可根據(jù)業(yè)務(wù)需求實(shí)現(xiàn)登錄邏輯,并頒發(fā)Token,后面的事情就交給 Light Security ,讓它給你搞定。這樣相對更加靈活,更重要的是——你也不再需要去學(xué)習(xí)用框架應(yīng)該怎么登錄。
