我有一个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。
基本上,我需要这个注解来避免权限的水平升级,也许有更好的解决方案?
1条答案
按热度按时间krcsximq1#
认为这是因为spring security支持的元注解只是简单地允许用户使用自定义注解(即
@CurrentUserAccessLevel
)引用@PreAuthorize(xxxxx)
,并且没有关于使用自定义注解的属性(即@CurrentUserAccessLevel
的userId
属性)来做一些动态安全配置的花哨行为,就像你正在尝试做的那样。所以@CurrentUserAccessLevel
的userId
是无用的,你可以删除它。@PreAuthorize
表达式中的#userId
指的是用@CurrentUserAccessLevel
注解的方法的参数名。因此,如果您将其更改为#studentId
,则可以正常工作,因为getUserCourseDetails()
具有方法参数名称Long studentId
如果你不想将方法的参数名更改为
userId
,你可以使用@P
来指定它的值,比如: