I am using undertow as my HTTP library and want to verify the JWT token and HTTP method of every request. I don't want to implement the verification in every HttpHandler
. Is this the right way to do it?
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
}
}
A more reusable and recommended approach would be to stick with the Undertow HttpHandler API and to chain handlers together.
First, as you already proposed, your JWT authentication handler, checking for an incoming token in the request:
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);
}
});
}
}
One difference though, it simply implements the HttpHandler interface and expects a next HttpHandler to call in case of success. Before calling the handleRequest method on the next handler, note the line to add the current valid token as an exchange attachment. Attachments are a way to pass data between handlers.
Then, your HelloHandler simply expects a JwtToken from the exchange attachments (note that this is just a guess, I don't know what JWT library do you use, this is simply the type of the token variable in your example.)
public class HelloHandler implements HttpHandler {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
JwtToken token = exchange.getAttachment(JWT_TOKEN);
...
}
}
This handler will only be called if the request authentication is successful.
As you probably know, handlers are meant to be chained together:
Undertow.builder()
.addHttpListener(8080, "0.0.0.0")
.setHandler(new JwtAuthHandler(new HelloHandler()))
.build().start();
If you stick with the HttpHandler API, you can easily integrate and use existing handlers that Undertow provides, look here .
Your approach will force a subclass to implement handleVerifiedRequest
but will also allow someone to reimplement handleRequest
to circumvent your verification. To prevent a subclass from doing so, add the final
keyword to the original method in your abstract class.
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);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.