Как выполнить авторизацию пользователя с помощью токена Auth0 JWT на основе ролей - PullRequest
0 голосов
/ 26 мая 2020

Я пишу Spring Boot REST API и использую токены JWT. Теперь я пытаюсь создать авторизацию на основе ролей.

Это учебное пособие / реализация, которую я использую.

https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/

Я расширил эту реализацию с помощью дополнительной сущности Role и добавил отображение @ManyToMany в сущность ApplicationUser.

Теперь, насколько я понимаю, роли пользователей должны быть добавлены в токен (во время его создание). Итак, это существующий код:

@Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException {


        String token = JWT.create()
                .withSubject(((User) auth.getPrincipal()).getUsername())
                .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .sign(HMAC512(SECRET.getBytes()));
        res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
    }

Думаю, туда нужно добавить роли пользователей. Есть функция:

withArrayClaim(String Name, String[] items)

И вот моя первая проблема: я не уверен, как правильно это добавить.

Тогда это фрагменты, которые, насколько я понимаю, место, где проверяется токен:

private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
            // parse the token.
            String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
                    .build()
                    .verify(token.replace(TOKEN_PREFIX, ""))
                    .getSubject();

            if (user != null) {
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
            return null;
        }
        return null;
    }

Что меня беспокоит, так это фрагмент:

return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());

Я не понимаю, почему здесь null (Inteliij выделяет его как «учетные данные») и это новый ArrayList. Есть ли место, где я должен получить роли из токена и добавить их?

Я знаю, это довольно широкий вопрос, но я не смог найти других решений. Или, возможно, есть более простой способ создать простую аутентификацию / авторизацию токена JWT (на основе ролей).

Жду ваших ответов!

РЕДАКТИРОВАТЬ:

Или может быть, есть более простое решениеi - не сохранять роли пользователей внутри ключа, а только добавлять их во «второй» части, где null и новый ArrayList?

1 Ответ

1 голос
/ 26 мая 2020

Просто создайте предоставленные полномочия на основе ролей пользователя и аутентифицируйте пользователя с их помощью. Тогда аутентифицированный пользователь-участник будет содержать роли. Простой пример:

UserEntity userEntity = userRepository.findUserByEmail(user); // this depends of course on your implementation
if (userEntity == null) return null;
List<RoleEntity> roles = userEntity.getRoles();
Collection<GrantedAuthority> authorities = new HashSet<>();
roles.forEach((role) -> {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
});
return new UsernamePasswordAuthenticationToken(user, null, authorities);

Еще лучше, вы можете создать UserPrincipal, который реализует UserDetails из Spring Security.

public class UserPrincipal implements UserDetails {

private static final long serialVersionUID = 1L;
private final UserEntity userEntity;

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

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    Collection<GrantedAuthority> authorities = new HashSet<>();

    // Get user Roles
    Collection<RoleEntity> roles = userEntity.getRoles();

    if(roles == null) return authorities;

    roles.forEach((role) -> {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
    });

    return authorities;
}

@Override
public String getPassword() {
    return this.userEntity.getEncryptedPassword();
}

@Override
public String getUsername() {
    return this.userEntity.getEmail();
}

@Override
public boolean isAccountNonExpired() {
    return false;
}

@Override
public boolean isAccountNonLocked() {
    return false;
}

@Override
public boolean isCredentialsNonExpired() {
    return false;
}

@Override
public boolean isEnabled() {
    return false;
}
}

А чтобы использовать:

UserEntity userEntity = userRepository.findUserByEmail(user);
if (userEntity == null) return null;

UserPrincipal userPrincipal = new UserPrincipal(userEntity);
  return new UsernamePasswordAuthenticationToken(userPrincipal, null, userPrincipal.getAuthorities());
...