Rob Rob - 3 months ago 52
Java Question

Handling sessions and remembering logged in user with vertx

Currently when a user logs in to my web server using a web

POST
form, a custom authenticator and a custom user. I have the
CustomUser
put into the
Session
provided by the
RoutingContext
because, when using
RoutingContext#setUser
it only changes the user for that request and as soon as the user is redirected from the login processing page to their destination the
CustomUser
has been lost.

However, it also seems as though the
Session
in
RoutingContext
for the new page doesn't have any user stored in the entry where the auth placed the
CustomUser
, could this be sending a completely different
Session
?

Routing
:

//ROUTE DEFINITIONS
// SESSION AND COOKIE
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)).setNagHttps(false)); //TODO SSL
router.route().handler(CookieHandler.create());
// STATIC
router.route("/").handler(new StaticHandler()); //BASE
router.route("/admin").handler(new StaticHandler()); //ADMIN PAGE
// FORM REQUESTS
router.route("/login").handler(new AuthAndRegHandler(new CustomAuth(), dbController)); //LOGIN REQUEST
router.route("/logout").handler(new AuthAndRegHandler(new CustomAuth(), dbController)); //LOGOUT REQUEST
// AJAX
router.route("/ajax/updateInvoice").handler(new AjaxHandler());
// ERRORS
router.route().failureHandler(new ErrorHandler());
router.route().handler(handle -> {
handle.fail(404);
});
//END DEFINITIONS


AuthAndRegHandler
:

public class AuthAndRegHandler extends AuthHandlerImpl {

private DatabaseController db;
private CustomAuth authProvider;

public AuthAndRegHandler(CustomAuth authProvider, DatabaseController db) {
super(authProvider);
this.db = db;
this.authProvider = authProvider;
}

@Override
public void handle(RoutingContext event) {
Logger log = LoggerFactory.getLogger(this.getClass());
HttpServerResponse response = event.response();
HttpServerRequest request = event.request();
Session session = event.session();
String requestedPath = request.path();

authProvider.setJdbc(db.getJdbc()); //returns a JDBCClient

if(requestedPath.equalsIgnoreCase("/login")) {
if(request.method() != HttpMethod.POST)
event.fail(500);
else {
request.setExpectMultipart(true);
request.endHandler(handle -> {
MultiMap formAtts = request.formAttributes();
String email = formAtts.get("email");
String pw = formAtts.get("password");

log.info(email + ":" + pw + " login attempt");

authProvider.authenticate(new JsonObject()
.put("username", email)
.put("password", pw), res -> {
if(res.succeeded()) {
CustomUser userToSet = (CustomUser) res.result();

session.put("user", userToSet);
log.info("Login successful for " + email);
response.putHeader("Location", "/").setStatusCode(302).end();
} else {
event.fail(500);
log.error("Auth error for " + request.host());
}
});
});
}
}
}
}


CustomAuth
returns true every time for testing purposes.

StaticHandler


CustomUser user = session.get("user");
event.setUser(user);
response.putHeader("Content-Type", "text/html");

if(user != null) {
log.info(user.principal().getString("email") + " user detected");
event.setUser(user);
} else
log.info("Null user request detected"); //Constantly outputs, even after a login form has been submitted


I'm not entirely sure what's going wrong here. Vertx has sub-optimal documentation for a rookie like myself on session and handling things without their out-of-the-box implementations. Any help on how to log someone in and maintain their session like a normal website would be appreciated.

Answer

For those who stumble upon the same problem, but usually skip the comments:

Vert.x SessionHandler depends on CookieHandler, and the order is important here.

From the Vert.x examples:

router.route().handler(CookieHandler.create());
router.route().handler(sessionHandler);