2016-12-16 10 views
2

Я использую платформу в качестве моей HTTP-библиотеки и хочу проверить токен JWT и метод HTTP для каждого запроса. Я не хочу выполнять проверку в каждом HttpHandler. Правильно ли это?Вызов абстрактного метода из обратного вызова внутри абстрактного класса

Handler.java

public abstract class Handler implements HttpHandler { 

    private HttpString[] methods; 

    Handler(HttpString... methods) { 
     this.methods = methods; 
    } 

    @Override 
    public void handleRequest(HttpServerExchange httpServerExchange) throws Exception { 
     // verifying HTTP method 
     boolean verified = false; 
     for (HttpString method : methods) { 
      if (httpServerExchange.getRequestMethod().equals(method)) { 
       verified = true; 
       break; 
      } 
     } 

     if (!verified) { 
      // return http 405, cause: invalid HTTP method 
      httpServerExchange.setStatusCode(StatusCodes.METHOD_NOT_ALLOWED); 
      httpServerExchange.getResponseSender().send(Variables.Response.EMPTY); 
     } 

    // verifying JWT token 
    String jwt = httpServerExchange.getRequestHeaders().get("jwt", 0); 
    JWT.verifyToken(jwt) 
      .addListener(token -> { 
       if (token != null) { 
        handleVerifiedRequest(httpServerExchange, token); 
       } else { 
        // return http 400, cause: JWT invalid 
        httpServerExchange.setStatusCode(StatusCodes.UNAUTHORIZED); 
        httpServerExchange.getResponseSender().send(Variables.Errors.INVALID_JWT); 
       } 
      }); 
    } 

    public abstract void handleVerifiedRequest(HttpServerExchange httpServerExchange, String Token); 
} 

HelloHandler.java

public class HelloHandler extends Handler { 

    public HelloHandler(HttpString... methods) { 
     super(methods); 
    } 

    @Override 
    public void handleVerifiedRequest(HttpServerExchange httpServerExchange, String Token) { 
     // .. do something 
    } 
} 
+0

не похоже, что с вашим решением что-то не так. – aiguy

+0

@aiguy Прохладный, спасибо! Это первый раз. Реализован абстрактный класс.: D – tom12e

+0

Использование этого подхода позволит вам связать другие обработчики. Я бы предположил, что вы придерживаетесь API Undertow (HttpHandler и Exchange Attachments.) Я могу подробно рассказать вам, если вы заинтересованы. – aramaki

ответ

3

Более повторного использования и рекомендуемый подход будет придерживаться API Undertow HttpHandler и обработчиков цепи вместе.

Во-первых, как вы уже предложили, ваш JWT обработчик аутентификации, проверки входящего маркера в запросе:

public class JwtAuthHandler implements HttpHandler { 

    AttachmentKey<JwtToken> JWT_TOKEN = AttachmentKey.create(JwtToken.class); 

    private final HttpHandler next; 
    public JwtAuthHandler(HttpHandler next) { 
    this.next = next; 
    } 

    @Override 
    public void handleRequest(HttpServerExchange exchange) throws Exception { 
    ... 
    JWT.verifyToken(jwt) 
     .addListener(token -> { 
      if (token != null) { 
      exchange.putAttachment(JWT_TOKEN, token); 
      next.handleRequest(exchange); 
      } else { 
      // return http 400, cause: JWT invalid 
      httpServerExchange.setStatusCode(StatusCodes.UNAUTHORIZED); 
      httpServerExchange.getResponseSender().send(Variables.Errors.INVALID_JWT); 
      } 
     }); 
    } 
} 

Одно различие, хотя, это просто реализует интерфейс HttpHandler и ожидает следующий HttpHandler в звоните в случае успеха. Перед вызовом метода handleRequest на следующем обработчике обратите внимание на строку, чтобы добавить текущий действительный токен в качестве вложения обмена. Вложения - это способ передачи данных между обработчиками.

Затем ваш HelloHandler просто ожидает JwtToken от привязанностей обмена (обратите внимание, что это только предположение, я не знаю, что библиотека JWT вы используете, это просто тип маркеров переменного в вашем примере.)

public class HelloHandler implements HttpHandler { 

    @Override 
    public void handleRequest(HttpServerExchange exchange) throws Exception { 
    JwtToken token = exchange.getAttachment(JWT_TOKEN); 
    ... 
    } 
} 

Этот обработчик будет вызываться только в том случае, если аутентификация запроса прошла успешно.

Как вы, наверное, знаете, обработчики предназначены для прикован вместе:

Undertow.builder() 
    .addHttpListener(8080, "0.0.0.0") 
    .setHandler(new JwtAuthHandler(new HelloHandler())) 
    .build().start(); 

Если придерживаться HttpHandler API, вы можете легко интегрировать и использовать существующие обработчики, которые Undertow обеспечивает, смотрите here.

1

Ваш подход заставит подкласс реализовать handleVerifiedRequest, но также позволит кому-то переописать handleRequest обойти вашу проверку. Чтобы этот подкласс не выполнялся, добавьте ключевое слово final в исходный метод в абстрактном классе.

public abstract class Handler implements HttpHandler { 
    // ... // 

    @Override 
    public final void handleRequest(HttpServerExchange httpServerExchange) throws Exception { 
     // ... your verification code ... // 
    } 

    public abstract void handleVerifiedRequest(HttpServerExchange httpServerExchange, String Token); 
}