如何使用用户ID作为自定义认证注解的参数?

问题描述 投票:0回答:1

我有一个 REST API:

   @CurrentUserAccessLevel(userId = "#studentId")
   @GetMapping(value = "/{course-code}/users/{student-id}")
   public UserCourseDetailsDto getUserCourseDetails(@PathVariable(value = "course-code") final Long courseCode,
                                                    @PathVariable(value = "student-id") final Long studentId) {
       return userCourseService.getUserCourseDetails(studentId, courseCode);
   }

和自定义身份验证注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@PreAuthorize("@applicationUserDetailsService.hasAccessToResourceOwnedBy(#userId)")
public @interface CurrentUserAccessLevel {
    String userId();
}

注释使用方法 hasAccessToResourceOwnedBy(userId):

public boolean hasAccessToResourceOwnedBy(final Long userId) {
        final User currentUser = userService.resolveCurrentUser();
        return isAdmin(currentUser) || Objects.equals(currentUser.getId(), userId);
    }

但我的 userId 为 null。但是,如果我更换

@PreAuthorize("@applicationUserDetailsService.hasAccessToResourceOwnedBy(#userId)")

@PreAuthorize("@applicationUserDetailsService.hasAccessToResourceOwnedBy(#studentId)")

我获得了请求的用户ID。

基本上,我需要这个注释来避免权限的水平升级,也许有更好的解决方案?

java spring-boot annotations spring-expression
1个回答
0
投票

认为这是因为 Spring Security 支持的元注释只是简单地允许用户使用自定义注释(即

@CurrentUserAccessLevel
)来引用
@PreAuthorize(xxxxx)
并且没有使用 self 属性的奇特行为-定义的注释(即
userId
@CurrentUserAccessLevel
属性)来执行一些动态安全配置,就像您想要做的那样。所以
userId
@CurrentUserAccessLevel
没有用,可以去掉。

#userId
表达式中的
@PreAuthorize
指的是用
@CurrentUserAccessLevel
注解的方法的参数名称。因此,如果将其更改为
#studentId
,则它会起作用,因为
getUserCourseDetails()
有一个方法参数名称
Long studentId

如果您不想将方法的参数名称更改为

userId
,您可以使用
@P
来指定其值,例如:

@CurrentUserAccessLevel
public UserCourseDetailsDto getUserCourseDetails( Long courseCode, @P("userId") Long studentId){
  
}
© www.soinside.com 2019 - 2024. All rights reserved.