Служба Zuul & Micro: не удалось вычислить выражение 'hasRole (' ADMIN ') или #userId == Principal.userId' - PullRequest
0 голосов
/ 21 апреля 2020

Я разрабатываю приложение с микро сервисами. На самом деле это приложение имеет:

  • Eureka discovery (8010)
  • Zuul gateway (8011)
  • Springboot-приложение для управления пользователями (случайный порт)

Чтобы добраться до пользователя API, я использую zuul: Например, у меня есть эти точки входа:

// delete a specific user
[DELETE] http://localhost:8011/users-ms/users/4RGh4MKkqdpXxYsJXLWRYXZKe6krsr
// get all users
[GET] http://localhost:8011/users-ms/users

Пока все хорошо. Моя проблема в том, что я хотел бы разрешить только «Администраторам» и «Владельцам» удалять свой профиль.

Для этого в моем пользовательском микро-сервисе у меня есть этот метод контроллера:

@PreAuthorize("hasRole('ADMIN') or #userId == principal.userId")
@Transactional
@DeleteMapping(path = "/{userId}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<OperationStatusResponseModel> deleteUser(@PathVariable String userId) {
    log.info("# deleteUser() was called");

    OperationStatusResponseModel returnValue = new OperationStatusResponseModel();

    userService.deleteUser(userId);
    returnValue.setOperationName(RequestOperationName.DELETE.name());
    returnValue.setOperationResult(RequestOperationResult.SUCCESS.getOperationName());

    return new ResponseEntity<>(returnValue, HttpStatus.OK);
}

Я также реализовал класс UserPrincipal:

publi c Класс UserPrincipal реализует UserDetails {

private static final long serialVersionUID = 7464059818443209139L;

private UserEntity userEntity;

@Getter @Setter
private String userId;

public UserPrincipal(UserEntity userEntity) {
    this.userEntity = userEntity;
    this.userId = userEntity.getUserId();
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    Collection<GrantedAuthority> authorities = new HashSet<>();
    Collection<AuthorityEntity> authorityEntities = new HashSet<>();
    // get user roles
    Collection<RoleEntity> roles = userEntity.getRoles();
    if (roles == null) {
        return authorities; // null
    }
    // get user roles
    roles.forEach((role) ->{
        authorities.add(new SimpleGrantedAuthority(role.getName()));
        authorityEntities.addAll(role.getAuthorities());
    });
    // get user authorities
    authorityEntities.forEach(authorityEntity -> {
        authorities.add(new SimpleGrantedAuthority(authorityEntity.getName()));
    });

    return authorities;
}

И в моем UserServiceImpl:

@ Service publi c Класс UserServiceImpl реализует UserService {

private UserRepository userRepository;
private PasswordResetTokenRepository passwordResetTokenRepository;
private RoleRepository roleRepository;
private Utils utils;
private BCryptPasswordEncoder bCryptPasswordEncoder;
private AmazonSES amazonSES;

@Autowired
public UserServiceImpl(UserRepository userRepository,
                       PasswordResetTokenRepository passwordResetTokenRepository,
                       RoleRepository roleRepository,
                       AmazonSES amazonSES,
                       Utils utils,
                       BCryptPasswordEncoder bCryptPasswordEncoder) {
    this.userRepository = userRepository;
    this.passwordResetTokenRepository = passwordResetTokenRepository;
    this.roleRepository = roleRepository;
    this.amazonSES = amazonSES;
    this.utils = utils;
    this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}

// load user by username : the interface is extending UserDetailsService
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
    UserEntity userEntity = userRepository.findByEmail(email);
    if (userEntity == null)
        throw new UsernameNotFoundException(email);

    return new UserPrincipal(userEntity);
}

У меня есть спецификация c websecurity в zuul которые позволяют мне получить доступ к этим точкам входа и определенному c классу веб-безопасности, который разрешает только «вызов» с zuul IP-адреса.

Я получаю этот ответ из приложения:

{
    "timestamp": "2020-04-21T08:38:22.260+0000",
    "message": "Failed to evaluate expression 'hasRole('ADMIN') or #userId == principal.userId'"
}

Если точка входа доступна только для ADMIN, я получаю ошибку 500, что нормально, если у меня нет роли ADMIN ,

...