想要控制好权限,这8个注解必须知道!

laomugua
发布于 2023-9-14 16:17
浏览
0收藏

大家好,我是不才陈某~

在​​码猿慢病云管理系统​​采用的是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)的启动类如下:

想要控制好权限,这8个注解必须知道!-鸿蒙开发者社区

如果是直接集成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个注解总结如下:

  1. ​@PostAuthorize​​:在目标方法执行之后进行权限校验。
  2. ​@PostFilter​​:在目标方法执行之后对方法的返回结果进行过滤。
  3. ​@PreAuthorize​​:在目标方法执行之前进行权限校验。
  4. ​@PreFilter​​:在目标方法执行之前对方法参数进行过滤。
  5. ​@Secured​​:访问目标方法必须具备相应的角色。
  6. ​@DenyAll​​:拒绝所有访问。
  7. ​@PermitAll​​:允许所有访问。
  8. ​@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​​中的分页查询住院患者接口如下:

想要控制好权限,这8个注解必须知道!-鸿蒙开发者社区

这里的​​@PreAuthorize("@pms.hasPermission('inhos_patinfohot_get')" )​​​则是对用户的权限进行拦截校验,只有拥有​​inhos_patinfohot_get​​权限的用户才能访问这个接口。

而这里是直接通过SPEL表达式调用IOC容器中的方法进行拦截校验,代码如下:

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

想要控制好权限,这8个注解必须知道!-鸿蒙开发者社区

逻辑很简单,从SecurityContext中获取用户的权限和指定的权限进行比较,校验通过则返回true。

总结

本篇文章介绍了Spring Security 中内置的8个权限注解以及​​码猿慢病云管理系统​​中的实践,这个权限注解的使用是必须将权限下放到微服务鉴权才能用到,如果你的系统是在网关处统一鉴权则用不到。


文章转载自公众号: 码猿技术专栏

分类
已于2023-9-14 16:17:01修改
收藏
回复
举报
回复
    相关推荐