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