我有一个自定义注释,用于检查当前用户是否具有作为注释参数传递的所需权限。有一个例外:如果用户想要更改另一个用户的数据,他必须具有更高的等级。所以我需要传递应该更改的用户(或用户对象)的ID。在下面的其余调用中,这将是userDto
的ID。问题是,我无法通过userDto.getId()
,因为userDto
尚无法解析。请参阅以下代码:
使用相关注释在其余控制器中调用方法:(@ RequiresPrivileges)
@RequiresPrivileges(value = {PrivilegeType.USRMGA, PrivilegeType.USRMGO}, usrMgmntObj = User.class, usrMgmntObjId = userDto.getId()) // at this stage, userDto is not known
@PutMapping
public ResponseEntity<List<DetailedUserDto>> update(@RequestBody UserDto userDto) {
return new ResponseEntity<>(userService.update(userDto), HttpStatus.OK);
}
@interface RequiresPrivileges:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiresPrivileges {
/**
* Required privileges to access the method
*/
PrivilegeType[] value();
/**
* If user wants to make changes to another user or usergroup, the rank needs to be checked. To do so,
* the object class (user or usergroup) and the suiting id needs to be provided
*/
Class usrMgmntObj() default Object.class;
long usrMgmntObjId() default -1;
}
@Aspect of Annotation
@Around("@annotation(RequiresPrivileges)")
public Object requiresPrivileges(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
PrivilegeType[] privileges = method.getAnnotation(RequiresPrivileges.class).value();
Class usrMgmntObjClass = method.getAnnotation(RequiresPrivileges.class).usrMgmntObj();
long usrMgmntObjId = method.getAnnotation(RequiresPrivileges.class).usrMgmntObjId();
boolean authorized = false;
// if the user wants to change a user management object (user or usergroup), the rank has to be higher than the
// one the user wants to change. BUT user with the privilege PrivilegeType.USRMGA may edit without checking the
// rank
if ((usrMgmntObjClass == User.class || usrMgmntObjClass == Usergroup.class) && usrMgmntObjId > -1) {
if (usrMgmntObjClass == User.class) {
if (!authorizationService.hasHigherRank(currentUserService.getCurrentUserId(), usrMgmntObjId)) {
if (authorizationService.hasPrivileges(privileges, currentUserService.getCurrentUserId())) {
// user is authorized
authorized = true;
}
}
}
}
// check for privileges if user is not authorized already
if (!authorized) {
if (authorizationService.hasPrivileges(privileges, currentUserService.getCurrentUserId())) {
// user is authorized
return joinPoint.proceed();
} else {
// user is not authorized
throw new AccessNotAllowedException(currentUserService.getCurrentUserId());
}
} else {
return joinPoint.proceed();
}
}
如何将UserDto
(或整个对象)的ID传递给注释?是否可以使用userDto
为参数ElementType.PARAMETER
创建另一个注释并在那里执行逻辑?
答案 0 :(得分:1)
如果您的应用程序使用Spring Security,那么您可以简单地使用Spring的@PreAuthorize
,而不是编写自己的注释。另外,如果您不想按照现在的方式进行操作,那么您可以使用UserDto
从方法的参数中获取JoinPoint#getArgs()
。