/** * Copyright 2011-2014 the original author or authors. */ package com.jetdrone.vertx.yoke.middleware; import io.vertx.core.http.HttpMethod; import org.jetbrains.annotations.NotNull; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; import com.jetdrone.vertx.yoke.Middleware; import com.jetdrone.vertx.yoke.Yoke; import com.jetdrone.vertx.yoke.util.Utils; public class FormAuth extends Middleware { private final AuthHandler authHandler; private String loginURI; private String logoutURI; private String loginTemplate; private String userLoginTemplate; private final boolean forceSSL; public FormAuth(@NotNull final AuthHandler authHandler) { this(false, authHandler); } public FormAuth(final boolean forceSSL, @NotNull final AuthHandler authHandler) { this(forceSSL, "/login", "/logout", null, authHandler); } public FormAuth(final boolean forceSSL, @NotNull final String loginURI, @NotNull final String logoutURI, final String loginTemplate, @NotNull final AuthHandler authHandler) { this.authHandler = authHandler; this.loginURI = loginURI; this.logoutURI = logoutURI; this.userLoginTemplate = loginTemplate; this.forceSSL = forceSSL; if (this.userLoginTemplate == null) { this.loginTemplate = Utils.readResourceToBuffer(getClass(), "login.html").toString(); } } @Override public Middleware init(@NotNull final Yoke yoke, @NotNull final String mount) { super.init(yoke, mount); // trim the initial slash String correctedMount = mount; if (mount.endsWith("/")) { correctedMount = correctedMount.substring(0, correctedMount.length() - 1); } loginURI = correctedMount + loginURI; logoutURI = correctedMount + logoutURI; return this; } @Override public void handle(@NotNull final YokeRequest request, @NotNull final Handler<Object> next) { if (request.path().equals(loginURI)) { if (HttpMethod.GET.equals(request.method())) { if (loginTemplate != null) { // render internal login request.response().setContentType("text/html"); request.response().end( loginTemplate.replace("{title}", (String) request.get("title")) .replace("{action}", loginURI + "?redirect_url=" + Utils.encodeURIComponent(request.getParam("redirect_url", "/"))) .replace("{message}", "")); } else { // render login request.response().render(userLoginTemplate, next); } return; } if (HttpMethod.POST.equals(request.method())) { if (forceSSL && !request.isSSL()) { // SSL is required but the post is insecure next.handle(400); return; } authHandler.handle(request.getFormAttribute("username"), request.getFormAttribute("password"), new Handler<JsonObject>() { @Override public void handle(JsonObject user) { if (user != null) { JsonObject session = request.createSession(); session.put("user", request.getFormAttribute("username")); // get the redirect_url parameter String redirect = request.getParam("redirect_url", "/"); request.response().redirect(Utils.decodeURIComponent(redirect)); } else { if (loginTemplate != null) { // render internal login request.response().setContentType("text/html"); request.response().setStatusCode(401); request.response().end( loginTemplate.replace("{title}", (String) request.get("title")) .replace("{action}", loginURI + "?redirect_url=" + Utils.encodeURIComponent(request.getParam("redirect_url", "/"))) .replace("{message}", "Invalid username and/or password, please try again.")); } else { next.handle(401); } } } }); return; } } if (request.path().equals(logoutURI)) { if (HttpMethod.GET.equals(request.method())) { // remove session from storage request.destroySession(); // get the redirect_url parameter String redirect = request.getParam("redirect_url", "/"); request.response().redirect(Utils.decodeURIComponent(redirect)); return; } } // all others continue next.handle(null); } public final Middleware RequiredAuth = new Middleware() { @Override public void handle(@NotNull final YokeRequest request, @NotNull final Handler<Object> next) { JsonObject session = request.get("session"); if (session != null) { if (session.getString("id") != null) { next.handle(null); return; } } String redirect = request.getParam("redirect_url", Utils.encodeURIComponent(request.uri())); request.response().redirect(loginURI + "?redirect_url=" + Utils.decodeURIComponent(redirect)); } }; }