电竞比分网-中国电竞赛事及体育赛事平台

分享

想要控制好權(quán)限,這8個(gè)注解必須知道!

 woh5r1ofyffxnh 2023-08-07 發(fā)布于浙江

大家好,我是不才陳某~

碼猿慢病云管理系統(tǒng)采用的是Spring Cloud 集成Spring Security OAuth2的方式實(shí)現(xiàn)認(rèn)證、鑒權(quán),其中涉及到的一個(gè)重要問題則是數(shù)據(jù)權(quán)限的過濾,今天就來介紹一下實(shí)現(xiàn)的方案。

在之前的文章中曾經(jīng)介紹過通過自定義的三個(gè)注解 @RequiresLogin@RequiresPermissions 、 @RequiresRoles 實(shí)現(xiàn)微服務(wù)的鑒權(quán)其實(shí)就是參考Spring Security 內(nèi)置的注解實(shí)現(xiàn),有想要了解的請(qǐng)看:3 個(gè)注解,優(yōu)雅的實(shí)現(xiàn)微服務(wù)鑒權(quán)

在介紹數(shù)據(jù)權(quán)限之前,先來看下Spring Security 中內(nèi)置的8個(gè)權(quán)限注解,只有理解了這8個(gè)注解,對(duì)于理解碼猿慢病云管理系統(tǒng)中的實(shí)現(xiàn)方案就非常easy了。

Spring Security 內(nèi)置的權(quán)限注解是將鑒權(quán)下放到各個(gè)微服務(wù),想要了解在網(wǎng)關(guān)處統(tǒng)一鑒權(quán)處理的請(qǐng)看之前分享的文章:實(shí)戰(zhàn)干貨!Spring Cloud Gateway 整合 OAuth2.0 實(shí)現(xiàn)分布式統(tǒng)一認(rèn)證授權(quán)!

碼猿慢病云管理系統(tǒng)已在星球中持續(xù)更新,想要加入的私信!

Spring Security 中的權(quán)限注解

Spring Security 中支持多種數(shù)據(jù)權(quán)限注解,若想使用內(nèi)置的注解,首先需要通過@EnableGlobalMethodSecurity這個(gè)注解開啟權(quán)限注解的支持,代碼如下:

/**
 * @author 公眾號(hào):碼猿技術(shù)專欄
 * 自定義資源服務(wù)注解
 * {@link com.code.ape.codeape.common.security.annotation.EnableCodeapeResourceServer}
 */

@Documented
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import({ CodeapeResourceServerAutoConfiguration.classCodeapeResourceServerConfiguration.class })
public @interface EnableCodeapeResourceServer 
{}

碼猿慢病云管理系統(tǒng)中是將Spring Security集成為一個(gè)Spring Boot Starter,因此需要一個(gè)直接開啟對(duì)于Spring Security的支持,EnableCodeapeResourceServer是自定義的資源服務(wù)注解,便于一鍵導(dǎo)入資源服務(wù)配置,只要是資源服務(wù),只需要在資源服務(wù)配置類上添加這個(gè)注解即可。

比如設(shè)備服務(wù)(codeape-device-biz)的啟動(dòng)類如下:

如果是直接集成Spring Security ,那么直接在配置類標(biāo)注@EnableGlobalMethodSecurity這個(gè)注解也是一樣效果,代碼如下:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}

@EnableGlobalMethodSecurity注解的三個(gè)屬性如下:

  • prePostEnabled:設(shè)置為true,將會(huì)開啟 Spring Security 提供的四個(gè)權(quán)限注解,@PostAuthorize、@PostFilter、@PreAuthorize 以及 @PreFilter,這四個(gè)注解支持權(quán)限表達(dá)式,支持 SpEL,功能比較豐富。
  • securedEnabled:設(shè)置為true,將會(huì)開啟 Spring Security 提供的 @Secured 注解,該注解不支持權(quán)限表達(dá)式。
  • jsr250Enabled:設(shè)置為true,將會(huì)開啟 JSR-250 提供的注解,主要包括 @DenyAll、@PermitAll 以及 @RolesAllowed 三個(gè)注解,這些注解也不支持權(quán)限表達(dá)式。

以上的8個(gè)注解總結(jié)如下:

  1. @PostAuthorize:在目標(biāo)方法執(zhí)行之后進(jìn)行權(quán)限校驗(yàn)。
  2. @PostFilter:在目標(biāo)方法執(zhí)行之后對(duì)方法的返回結(jié)果進(jìn)行過濾。
  3. @PreAuthorize:在目標(biāo)方法執(zhí)行之前進(jìn)行權(quán)限校驗(yàn)。
  4. @PreFilter:在目標(biāo)方法執(zhí)行之前對(duì)方法參數(shù)進(jìn)行過濾。
  5. @Secured:訪問目標(biāo)方法必須具備相應(yīng)的角色。
  6. @DenyAll:拒絕所有訪問。
  7. @PermitAll:允許所有訪問。
  8. @RolesAllowed:訪問目標(biāo)方法必須具備相應(yīng)的角色。

其實(shí)在日常開發(fā)中使用前四個(gè)注解已經(jīng)完全夠用,且支持靈活的SPEL權(quán)限表達(dá)式,方便定制。因此只需要設(shè)置prePostEnabled = true

權(quán)限注解使用

接下來就來簡單介紹一下這8個(gè)權(quán)限注解的使用。

1. @PreAuthorize

@PreAuthorize這個(gè)注解在方法執(zhí)行之前進(jìn)行安全校驗(yàn),支持SPEL,比如在接口使用代碼如下:

@RestController
@RequestMapping
public class HelloService {
    @PreAuthorize("hasRole('IN_HOS_NURSE')")
    @GetMapping
    public String hello() {
        return "hello";
    }
}

@PreAuthorize("hasRole('IN_HOS_NURSE')")代碼含義則是只有擁有住院護(hù)士的角色的用戶才能訪問這個(gè)接口。這里用到了hasRole這個(gè)權(quán)限表達(dá)式,表示擁有某個(gè)角色

2. @PreFilter

@PreFilter這個(gè)注解主要是對(duì)參數(shù)進(jìn)行過濾,其中兩個(gè)屬性如下:

  • value :SPEL表達(dá)式校驗(yàn)
  • filterTarget:多個(gè)參數(shù)的情況下,指定對(duì)某個(gè)參數(shù)校驗(yàn)

使用如下:

@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ù)校驗(yàn),平常所有的數(shù)據(jù)校驗(yàn)一般是在方法執(zhí)行之前,所以一般結(jié)合@PreAuthorize使用。

PostAuthorize中內(nèi)置了一個(gè)returnObject返回值,對(duì)方法的返回值校驗(yàn),使用如下:

@RestController
@RequestMapping
public class HelloService {
    @PostAuthorize(value = "returnObject.id==1")
    @GetMapping
    public Obj hello(List<Obj> obj,Integer a) {
        return "hello";
    }
}

這個(gè)接口的返回值的id必須等于1才會(huì)通過,否則將會(huì)拋出異常。

4. @PostFilter

@PostFilter 注解是在目標(biāo)方法執(zhí)行之后,對(duì)目標(biāo)方法的返回結(jié)果進(jìn)行過濾,該注解中包含了一個(gè)內(nèi)置對(duì)象 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)限注解,不同于前面四個(gè)注解,該注解不支持權(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)限才能訪問這個(gè)接口。

@Secured能夠做的,@PreAuthorize也都能做,且給的更多!

6. @DenyAll

@DenyAllJSR-250 提供的方法注解,顧名思義,拒絕所有請(qǐng)求。

@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)添加在類上時(shí),表示該注解對(duì)類中的所有方法生效;如果類上和方法上都有該注解,并且起沖突,則以方法上的注解為準(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)限才能訪問這個(gè)接口。

根據(jù)上述的介紹,大致理解了這8個(gè)注解,實(shí)際項(xiàng)目中建議使用@PostAuthorize、@PostFilter、@PreAuthorize 以及 @PreFilter這四個(gè)注解,完全夠用了!

慢病云管理系統(tǒng)的實(shí)踐

碼猿慢病云管理系統(tǒng)中使用的權(quán)限注解是@PreAuthorize,在接口執(zhí)行之前對(duì)數(shù)據(jù)權(quán)限進(jìn)行校驗(yàn)。

比如住院服務(wù)codeape-inhos-biz中的分頁查詢住院患者接口如下:

這里的@PreAuthorize("@pms.hasPermission('inhos_patinfohot_get')" )則是對(duì)用戶的權(quán)限進(jìn)行攔截校驗(yàn),只有擁有inhos_patinfohot_get權(quán)限的用戶才能訪問這個(gè)接口。

而這里是直接通過SPEL表達(dá)式調(diào)用IOC容器中的方法進(jìn)行攔截校驗(yàn),代碼如下:

com.code.ape.codeape.common.security.component.PermissionService#hasPermission

邏輯很簡單,從SecurityContext中獲取用戶的權(quán)限和指定的權(quán)限進(jìn)行比較,校驗(yàn)通過則返回true。

總結(jié)

本篇文章介紹了Spring Security 中內(nèi)置的8個(gè)權(quán)限注解以及碼猿慢病云管理系統(tǒng)中的實(shí)踐,這個(gè)權(quán)限注解的使用是必須將權(quán)限下放到微服務(wù)鑒權(quán)才能用到,如果你的系統(tǒng)是在網(wǎng)關(guān)處統(tǒng)一鑒權(quán)則用不到。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多