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

czq61nw1  于 2023-10-20  发布在  Spring
关注(0)|答案(1)|浏览(159)

我有一个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();
}

注解使用方法hasExcitToResourceOwnedBy(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。
基本上,我需要这个注解来避免权限的水平升级,也许有更好的解决方案?

krcsximq

krcsximq1#

认为这是因为spring security支持的元注解只是简单地允许用户使用自定义注解(即@CurrentUserAccessLevel)引用@PreAuthorize(xxxxx),并且没有关于使用自定义注解的属性(即@CurrentUserAccessLeveluserId属性)来做一些动态安全配置的花哨行为,就像你正在尝试做的那样。所以@CurrentUserAccessLeveluserId是无用的,你可以删除它。
@PreAuthorize表达式中的#userId指的是用@CurrentUserAccessLevel注解的方法的参数名。因此,如果您将其更改为#studentId,则可以正常工作,因为getUserCourseDetails()具有方法参数名称Long studentId
如果你不想将方法的参数名更改为userId,你可以使用@P来指定它的值,比如:

@CurrentUserAccessLevel
public UserCourseDetailsDto getUserCourseDetails( Long courseCode, @P("userId") Long studentId){
  
}

相关问题