如何将RequestBody中的对象传递给注释

时间:2017-09-26 08:43:06

标签: java spring rest annotations

我有一个自定义注释,用于检查当前用户是否具有作为注释参数传递的所需权限。有一个例外:如果用户想要更改另一个用户的数据,他必须具有更高的等级。所以我需要传递应该更改的用户(或用户对象)的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创建另一个注释并在那里执行逻辑?

1 个答案:

答案 0 :(得分:1)

如果您的应用程序使用Spring Security,那么您可以简单地使用Spring的@PreAuthorize,而不是编写自己的注释。另外,如果您不想按照现在的方式进行操作,那么您可以使用UserDto从方法的参数中获取JoinPoint#getArgs()