想要控制好權(quán)限,這八個注解必須知道!
在碼猿慢病云管理系統(tǒng)采用的是Spring Cloud 集成Spring Security OAuth2的方式實現(xiàn)認(rèn)證、鑒權(quán),其中涉及到的一個重要問題則是數(shù)據(jù)權(quán)限的過濾,今天就來介紹一下實現(xiàn)的方案。
在之前的文章中曾經(jīng)介紹過通過自定義的三個注解 @RequiresLogin、 @RequiresPermissions 、 @RequiresRoles 實現(xiàn)微服務(wù)的鑒權(quán)其實就是參考Spring Security 內(nèi)置的注解實現(xiàn),有想要了解的請看:3 個注解,優(yōu)雅的實現(xiàn)微服務(wù)鑒權(quán)
在介紹數(shù)據(jù)權(quán)限之前,先來看下Spring Security 中內(nèi)置的8個權(quán)限注解,只有理解了這8個注解,對于理解碼猿慢病云管理系統(tǒng)中的實現(xiàn)方案就非常easy了。
Spring Security 內(nèi)置的權(quán)限注解是將鑒權(quán)下放到各個微服務(wù),想要了解在網(wǎng)關(guān)處統(tǒng)一鑒權(quán)處理的請看之前分享的文章:實戰(zhàn)干貨!Spring Cloud Gateway 整合 OAuth2.0 實現(xiàn)分布式統(tǒng)一認(rèn)證授權(quán)!
Spring Security 中的權(quán)限注解
Spring Security 中支持多種數(shù)據(jù)權(quán)限注解,若想使用內(nèi)置的注解,首先需要通過@EnableGlobalMethodSecurity這個注解開啟權(quán)限注解的支持,代碼如下:
/**
* @author 公眾號:碼猿技術(shù)專欄
* 自定義資源服務(wù)注解
* {@link com.code.ape.codeape.common.security.annotation.EnableCodeapeResourceServer}
*/
@Documented
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import({ CodeapeResourceServerAutoConfiguration.class, CodeapeResourceServerConfiguration.class })
public @interface EnableCodeapeResourceServer {}
在碼猿慢病云管理系統(tǒng)中是將Spring Security集成為一個Spring Boot Starter,因此需要一個直接開啟對于Spring Security的支持,EnableCodeapeResourceServer是自定義的資源服務(wù)注解,便于一鍵導(dǎo)入資源服務(wù)配置,只要是資源服務(wù),只需要在資源服務(wù)配置類上添加這個注解即可。
比如設(shè)備服務(wù)(codeape-device-biz)的啟動類如下:
圖片
如果是直接集成Spring Security ,那么直接在配置類標(biāo)注@EnableGlobalMethodSecurity這個注解也是一樣效果,代碼如下:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
@EnableGlobalMethodSecurity注解的三個屬性如下:
- prePostEnabled:設(shè)置為true,將會開啟 Spring Security 提供的四個權(quán)限注解,@PostAuthorize、@PostFilter、@PreAuthorize 以及 @PreFilter,這四個注解支持權(quán)限表達(dá)式,支持 SpEL,功能比較豐富。
- securedEnabled:設(shè)置為true,將會開啟 Spring Security 提供的 @Secured 注解,該注解不支持權(quán)限表達(dá)式。
- jsr250Enabled:設(shè)置為true,將會開啟 JSR-250 提供的注解,主要包括 @DenyAll、@PermitAll 以及 @RolesAllowed 三個注解,這些注解也不支持權(quán)限表達(dá)式。
以上的8個注解總結(jié)如下:
- @PostAuthorize:在目標(biāo)方法執(zhí)行之后進(jìn)行權(quán)限校驗。
- @PostFilter:在目標(biāo)方法執(zhí)行之后對方法的返回結(jié)果進(jìn)行過濾。
- @PreAuthorize:在目標(biāo)方法執(zhí)行之前進(jìn)行權(quán)限校驗。
- @PreFilter:在目標(biāo)方法執(zhí)行之前對方法參數(shù)進(jìn)行過濾。
- @Secured:訪問目標(biāo)方法必須具備相應(yīng)的角色。
- @DenyAll:拒絕所有訪問。
- @PermitAll:允許所有訪問。
- @RolesAllowed:訪問目標(biāo)方法必須具備相應(yīng)的角色。
其實在日常開發(fā)中使用前四個注解已經(jīng)完全夠用,且支持靈活的SPEL權(quán)限表達(dá)式,方便定制。因此只需要設(shè)置prePostEnabled = true
權(quán)限注解使用
接下來就來簡單介紹一下這8個權(quán)限注解的使用。
1. @PreAuthorize
@PreAuthorize這個注解在方法執(zhí)行之前進(jìn)行安全校驗,支持SPEL,比如在接口使用代碼如下:
@RestController
@RequestMapping
public class HelloService {
@PreAuthorize("hasRole('IN_HOS_NURSE')")
@GetMapping
public String hello() {
return "hello";
}
}
@PreAuthorize("hasRole('IN_HOS_NURSE')")代碼含義則是只有擁有住院護(hù)士的角色的用戶才能訪問這個接口。這里用到了hasRole這個權(quán)限表達(dá)式,表示擁有某個角色
2. @PreFilter
@PreFilter這個注解主要是對參數(shù)進(jìn)行過濾,其中兩個屬性如下:
- value :SPEL表達(dá)式校驗
- filterTarget:多個參數(shù)的情況下,指定對某個參數(shù)校驗
使用如下:
@RestController
@RequestMapping
public class HelloService {
@PreFilter(value = "obj.id!=1",filterTarget = "users")
@GetMapping
public String hello(List<Obj> obj,Integer a) {
return "hello";
}
}
3. @PostAuthorize
@PostAuthorize是在方法執(zhí)行之后進(jìn)行數(shù)據(jù)校驗,平常所有的數(shù)據(jù)校驗一般是在方法執(zhí)行之前,所以一般結(jié)合@PreAuthorize使用。
PostAuthorize中內(nèi)置了一個returnObject返回值,對方法的返回值校驗,使用如下:
@RestController
@RequestMapping
public class HelloService {
@PostAuthorize(value = "returnObject.id==1")
@GetMapping
public Obj hello(List<Obj> obj,Integer a) {
return "hello";
}
}
這個接口的返回值的id必須等于1才會通過,否則將會拋出異常。
4. @PostFilter
@PostFilter 注解是在目標(biāo)方法執(zhí)行之后,對目標(biāo)方法的返回結(jié)果進(jìn)行過濾,該注解中包含了一個內(nèi)置對象 filterObject,表示目標(biāo)方法返回的集合/數(shù)組中的具體元素:
@RestController
@RequestMapping
public class HelloService {
@PostFilter(value = "filterObject.id==1")
@GetMapping
public Obj hello(List<Obj> obj,Integer a) {
return "hello";
}
}
5. @Secured
@Secured 注解也是 Spring Security 提供的權(quán)限注解,不同于前面四個注解,該注解不支持權(quán)限表達(dá)式,只能做一些簡單的權(quán)限描述。
使用如下:
@RestController
@RequestMapping
public class HelloService {
@Secured({"ROLE_IN_HOS_NURSE","ROLE_IN_HOS_DOC"})
@GetMapping
public Obj hello(List<Obj> obj,Integer a) {
return "hello";
}
}
這段代碼表示只有當(dāng)前用戶擁有住院護(hù)士、住院醫(yī)生的權(quán)限才能訪問這個接口。
@Secured能夠做的,@PreAuthorize也都能做,且給的更多!
6. @DenyAll
@DenyAll 是 JSR-250 提供的方法注解,顧名思義,拒絕所有請求。
@RestController
@RequestMapping
public class HelloService {
@DenyAll
@GetMapping
public String hello() {
return "hello";
}
}
7. @PermitAll
@PermitAll 也是 JSR-250 提供的方法注解,顧名思義,允許所有訪問!
@RestController
@RequestMapping
public class HelloService {
@PermitAll
@GetMapping
public String hello() {
return "hello";
}
}
8. @RolesAllowed
@RolesAllowed 也是 JSR-250 提供的注解,可以添加在方法上或者類上,當(dāng)添加在類上時,表示該注解對類中的所有方法生效;如果類上和方法上都有該注解,并且起沖突,則以方法上的注解為準(zhǔn)。
@RestController
@RequestMapping
public class HelloService {
@RolesAllowed({"IN_HOS_NURSE","IN_HOS_DOC"})
@GetMapping
public Obj hello(List<Obj> obj,Integer a) {
return "hello";
}
}
這段代碼表示只有當(dāng)前用戶擁有住院護(hù)士、住院醫(yī)生的權(quán)限才能訪問這個接口。
根據(jù)上述的介紹,大致理解了這8個注解,實際項目中建議使用@PostAuthorize、@PostFilter、@PreAuthorize 以及 @PreFilter這四個注解,完全夠用了!
慢病云管理系統(tǒng)的實踐
在碼猿慢病云管理系統(tǒng)中使用的權(quán)限注解是@PreAuthorize,在接口執(zhí)行之前對數(shù)據(jù)權(quán)限進(jìn)行校驗。
比如住院服務(wù)codeape-inhos-biz中的分頁查詢住院患者接口如下:
圖片
這里的@PreAuthorize("@pms.hasPermission('inhos_patinfohot_get')" )則是對用戶的權(quán)限進(jìn)行攔截校驗,只有擁有inhos_patinfohot_get權(quán)限的用戶才能訪問這個接口。
而這里是直接通過SPEL表達(dá)式調(diào)用IOC容器中的方法進(jìn)行攔截校驗,代碼如下:
com.code.ape.codeape.common.security.component.PermissionService#hasPermission
圖片
邏輯很簡單,從SecurityContext中獲取用戶的權(quán)限和指定的權(quán)限進(jìn)行比較,校驗通過則返回true。
總結(jié)
本篇文章介紹了Spring Security 中內(nèi)置的8個權(quán)限注解以及碼猿慢病云管理系統(tǒng)中的實踐,這個權(quán)限注解的使用是必須將權(quán)限下放到微服務(wù)鑒權(quán)才能用到,如果你的系統(tǒng)是在網(wǎng)關(guān)處統(tǒng)一鑒權(quán)則用不到。
碼猿慢病云管理系統(tǒng)已經(jīng)在星球中陸續(xù)更新,目前更新內(nèi)容如下:
前言
01 項目架構(gòu)+業(yè)務(wù)介紹
02 三方組件介紹
03 服務(wù)端項目部署
04 前端項目部署
05 多租戶架構(gòu)設(shè)計
06 醫(yī)療系統(tǒng)中的權(quán)限如何設(shè)計?
07 項目搭建
08 關(guān)掉驗證碼登錄
09 開發(fā)平臺自動生成業(yè)務(wù)代碼
認(rèn)證鑒權(quán)
01 認(rèn)證登錄生成token
02 token檢驗、鑒權(quán)
03 token有效期設(shè)置
04 刷新token
05 檢查token
06 服務(wù)中如何獲取當(dāng)前登錄用戶信息?
07 接口對外暴露
08 接口只允許內(nèi)部調(diào)用怎么處理?
09 如何實現(xiàn)token中繼?
10 當(dāng)前登錄用戶身份信息如何異步傳遞?
11 科室權(quán)限如何定一個注解自動注入?
12 一個注解防止接口重復(fù)提交
13 8個權(quán)限注解玩轉(zhuǎn)鑒權(quán)
業(yè)務(wù)
01 科室管理
02 醫(yī)院管理
03 角色管理
04 菜單+權(quán)限管理