Аутентификация на основе ролей на конечных точках Restful в Java

Я пытаюсь реализовать какую-то аутентификацию на основе ролей. Я использую токены JWT. Я просматривал руководства, но все они упоминают использование «Spring boot». Как мне настроить аутентификацию на основе ролей на моей конечной точке покоя в Java? Желательно через какой-нибудь фильтр.

Я ищу способ просто добавить: @Role(Role.ADMIN) перед конечной точкой.

У меня уже настроены следующие классы:

  • Перечисленная роль:

    public enum Role {
        User,
        Admin
    }
    
  • Простой токен JWT:

    {
     "sub": "users/TzMUocMF4p",
     "exp": 1554646441,
     "username": "[email protected]",
     "ID": 6,
     "Role": "Admin",
     "iat": 1554641041
    }
    
  • Простая конечная точка CRUD

    @Path("User")
    public class UserResource {
    
       @EJB
       private UserDAO userappDAO;
    
    
       @GET
       @JWTTokenNeeded
       @Produces("application/json")
       public List<Userapp> all() {
           return userappDAO.getAll();
       }
    }
    
  • JWT проверяет (@JWTTokenNeeded) класс ниже:

    @javax.ws.rs.NameBinding
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    public @interface JWTTokenNeeded {
    }
    

    Собственно фильтр:

    @Provider
    @JWTTokenNeeded
    @Priority(Priorities.AUTHENTICATION)
    public class JWTTokenNeededFilter implements ContainerRequestFilter {
    
    
        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
    
    // Get the HTTP Authorization header from the request
    String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
    
    try {
        // Extract the token from the HTTP Authorization header
        String token = authorizationHeader.substring("Bearer".length()).trim();
        // Validate the token
        Jwts.parser().setSigningKey("MYSECRET".getBytes("UTF-8")).parseClaimsJws(token);
    
    }
    catch (Exception e) {
        requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
    }
    }
    }
    

Если пользователь не авторизован, я хочу выйти с помощью: requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());

Если пользователь авторизован, конечная точка должна делать свое дело.

Я думаю, что вы ищете реализацию @Interceptorstackoverflow.com/questions/18853221/…

j.seashell 07.04.2019 16:01

Взгляните на MicroProfile JWT (eclipse.org/community/eclipse_newsletter/2017/сентябрь/…). При этом вы получаете java.security.Principal, проанализированный из токена JWT, и можете использовать @RolesAllowed на своих конечных точках JAX-RS. Для получения дополнительной информации взгляните на следующий пост: rickpil.de/…

rieckpil 07.04.2019 19:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
2
2 115
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел рабочее решение. Он включает в себя добавление нескольких строк в интерфейс @JWTTokenNeeded и класс JWTTokenNeededFilter.

В итоге я получил следующий код:

JWTTokeNeededФильтр:

@Provider
@JWTTokenNeeded
@Priority(Priorities.AUTHENTICATION)
public class JWTTokenNeededFilter implements ContainerRequestFilter {
    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        // Get the HTTP Authorization header from the request
        String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

        try {
            // Extract the token from the HTTP Authorization header
            String token = authorizationHeader.substring("Bearer".length()).trim();
            // Validate the token
            Claims claims =  Jwts.parser().setSigningKey("MYSECRET".getBytes("UTF-8")).parseClaimsJws(token).getBody();

            Method method =resourceInfo.getResourceMethod();
            if ( method != null){
                // Get allowed permission on method
                JWTTokenNeeded JWTContext = method.getAnnotation(JWTTokenNeeded.class);
                Role permission =  JWTContext.Permissions();

                if (permission != Role.NoRights ) {
                    // Get Role from jwt
                    String roles = claims.get("Role", String.class);
                    Role roleUser = Role.valueOf(roles);

                    // if role allowed != role jwt -> UNAUTHORIZED
                    if (!permission.equals(roleUser)) {
                        throw new Exception("no roles");
                    }

                }
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
        }
    }
}

Интерфейс @JWTTokenNeeded:

@javax.ws.rs.NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface JWTTokenNeeded {
    Role Permissions() default Role.NoRights;
}

Разрешить роли доступ к конечной точке так же просто, как добавить @JWTTokenNeeded(Permissions = Role.Admin)

Вот пример:

@Path("User")
public class UserResource {
    @EJB
    private UserappDAO userDAO;


    @GET
    @JWTTokenNeeded(Permissions = Role.Admin)
    @Produces("application/json")
    public List<Userapp> all() {
        return userDAO.getAll();
    }
}

Другие вопросы по теме