返回

对于Springboot如何使用自定义注解+切面来实现接口权限的控制

后端

对于在Springboot中,利用自定义注解+切面来实现接口权限的控制这个大家应该都很熟悉,也有大量的博客来介绍整个的实现过程,整体来说思路如下:

  • 自定义一个权限校验的注解,包含参数value
  • 配置在Controller的方法上,表示该方法需要权限校验
  • 创建一个切面类,实现AspectJ的Before注解
  • 在Before注解的方法中,解析注解的参数value,并获取当前用户的权限列表
  • 检查当前用户的权限列表中是否包含注解参数value所指定的权限
  • 如果不包含,则抛出异常,阻止方法的执行
  • 如果包含,则允许方法继续执行

这种方式实现起来比较简单,但是也有一个缺点,就是需要在每个需要权限校验的方法上都添加自定义注解,比较繁琐。

为了解决这个问题,我们可以使用Spring Security来实现权限校验。Spring Security是一个功能强大的安全框架,可以帮助我们轻松实现权限校验、用户认证等功能。

Spring Security的权限校验原理与上面介绍的自定义注解+切面方式类似,也是通过在方法上添加注解的方式来实现。

但是,Spring Security提供了更多的注解和配置选项,可以让我们更灵活地实现权限校验。

例如,我们可以使用@PreAuthorize注解来指定方法所需的权限,也可以使用@PostAuthorize注解来指定方法执行后需要检查的权限。

此外,Spring Security还提供了丰富的用户认证机制,我们可以使用用户名/密码、OAuth2、OpenID Connect等方式来对用户进行认证。

综合来看,Spring Security是一个非常强大和灵活的安全框架,可以帮助我们轻松实现权限校验、用户认证等功能。

如何实现权限校验

1. 自定义注解

首先,我们需要自定义一个权限校验的注解。这个注解可以包含一个参数value,表示该方法需要权限校验。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckPermission {

    String value();

}

2. 配置注解

然后,我们需要在需要权限校验的方法上配置这个注解。

@Controller
public class UserController {

    @CheckPermission("user:add")
    @PostMapping("/add")
    public void addUser(@RequestBody User user) {
        // ...
    }

}

3. 创建切面类

接下来,我们需要创建一个切面类来拦截被@CheckPermission注解的方法。

@Aspect
@Order(1)
public class CheckPermissionAspect {

    @Before("@annotation(checkPermission)")
    public void checkPermission(JoinPoint joinPoint, CheckPermission checkPermission) {
        // ...
    }

}

4. 解析注解参数

在Before注解的方法中,我们需要解析注解的参数value,并获取当前用户的权限列表。

@Before("@annotation(checkPermission)")
public void checkPermission(JoinPoint joinPoint, CheckPermission checkPermission) {
    String permission = checkPermission.value();
    List<String> permissions = getCurrentUserPermissions();

    // ...
}

5. 检查权限

然后,我们需要检查当前用户的权限列表中是否包含注解参数value所指定的权限。

@Before("@annotation(checkPermission)")
public void checkPermission(JoinPoint joinPoint, CheckPermission checkPermission) {
    String permission = checkPermission.value();
    List<String> permissions = getCurrentUserPermissions();

    if (!permissions.contains(permission)) {
        throw new UnauthorizedException();
    }

    // ...
}

6. 抛出异常或允许方法继续执行

如果当前用户的权限列表中不包含注解参数value所指定的权限,我们需要抛出异常,阻止方法的执行。

@Before("@annotation(checkPermission)")
public void checkPermission(JoinPoint joinPoint, CheckPermission checkPermission) {
    String permission = checkPermission.value();
    List<String> permissions = getCurrentUserPermissions();

    if (!permissions.contains(permission)) {
        throw new UnauthorizedException();
    }

    // ...
}

如果当前用户的权限列表中包含注解参数value所指定的权限,则允许方法继续执行。

@Before("@annotation(checkPermission)")
public void checkPermission(JoinPoint joinPoint, CheckPermission checkPermission) {
    String permission = checkPermission.value();
    List<String> permissions = getCurrentUserPermissions();

    if (permissions.contains(permission)) {
        // ...
    }
}

7. 使用Spring Security实现权限校验

也可以使用Spring Security来实现权限校验。Spring Security是一个功能强大的安全框架,可以帮助我们轻松实现权限校验、用户认证等功能。

Spring Security的权限校验原理与上面介绍的自定义注解+切面方式类似,也是通过在方法上添加注解的方式来实现。

@PreAuthorize("hasAuthority('user:add')")
@PostMapping("/add")
public void addUser(@RequestBody User user) {
    // ...
}

但是,Spring Security提供了更多的注解和配置选项,可以让我们更灵活地实现权限校验。

例如,我们可以使用@PreAuthorize注解来指定方法所需的权限,也可以使用@PostAuthorize注解来指定方法执行后需要检查的权限。

@PreAuthorize("hasAuthority('user:add')")
@PostMapping("/add")
public void addUser(@RequestBody User user) {
    // ...
}

@PostAuthorize("hasAuthority('user:view')")
@GetMapping("/get")
public User getUser(@PathVariable Long id) {
    // ...
}

此外,Spring Security还提供了丰富的用户认证机制,我们可以使用用户名/密码、OAuth2、OpenID Connect等方式来对用户进行认证。

优点

  • 这种方式实现起来比较简单,只需要在需要权限校验的方法上添加自定义注解即可。
  • Spring Security提供了丰富的注解和配置选项,可以让我们更灵活地实现权限校验。
  • Spring Security提供了丰富的用户认证机制,我们可以使用用户名/密码、OAuth2、OpenID Connect等方式来对用户进行认证。

缺点

  • 需要在每个需要权限校验的方法上都添加自定义注解,比较繁琐。
  • Spring Security的配置比较复杂,需要花费一些时间来学习。