package org.jboss.resteasy.plugins.server.vertx; import io.vertx.core.Context; import io.vertx.core.Vertx; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; import org.apache.commons.codec.binary.Base64; import org.jboss.resteasy.core.SynchronousDispatcher; import org.jboss.resteasy.core.ThreadLocalResteasyProviderFactory; import org.jboss.resteasy.plugins.server.embedded.SecurityDomain; import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpResponse; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.util.HttpHeaderNames; import org.jboss.resteasy.util.HttpResponseCodes; import javax.ws.rs.core.SecurityContext; import java.io.IOException; import java.security.Principal; import java.util.List; /** * Helper/delegate class to unify Servlet and Filter dispatcher implementations * * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author Norman Maurer * @version $Revision: 1 $ */ public class RequestDispatcher { protected final SynchronousDispatcher dispatcher; protected final ResteasyProviderFactory providerFactory; protected final SecurityDomain domain; public RequestDispatcher(SynchronousDispatcher dispatcher, ResteasyProviderFactory providerFactory, SecurityDomain domain) { this.dispatcher = dispatcher; this.providerFactory = providerFactory; this.domain = domain; } public SynchronousDispatcher getDispatcher() { return dispatcher; } public SecurityDomain getDomain() { return domain; } public ResteasyProviderFactory getProviderFactory() { return providerFactory; } public void service(Context context, HttpServerRequest req, HttpServerResponse resp, HttpRequest vertxReq, HttpResponse vertxResp, boolean handleNotFound) throws IOException { try { ResteasyProviderFactory defaultInstance = ResteasyProviderFactory.getInstance(); if (defaultInstance instanceof ThreadLocalResteasyProviderFactory) { ThreadLocalResteasyProviderFactory.push(providerFactory); } SecurityContext securityContext; if (domain != null) { securityContext = basicAuthentication(vertxReq, vertxResp); if (securityContext == null) // not authenticated { return; } } else { securityContext = new VertxSecurityContext(); } try { ResteasyProviderFactory.pushContext(SecurityContext.class, securityContext); ResteasyProviderFactory.pushContext(Context.class, context); ResteasyProviderFactory.pushContext(HttpServerRequest.class, req); ResteasyProviderFactory.pushContext(HttpServerResponse.class, resp); ResteasyProviderFactory.pushContext(Vertx.class, context.owner()); if (handleNotFound) { dispatcher.invoke(vertxReq, vertxResp); } else { dispatcher.invokePropagateNotFound(vertxReq, vertxResp); } } finally { ResteasyProviderFactory.clearContextData(); } } finally { ResteasyProviderFactory defaultInstance = ResteasyProviderFactory.getInstance(); if (defaultInstance instanceof ThreadLocalResteasyProviderFactory) { ThreadLocalResteasyProviderFactory.pop(); } } } private SecurityContext basicAuthentication(HttpRequest request, HttpResponse response) throws IOException { List<String> headers = request.getHttpHeaders().getRequestHeader(HttpHeaderNames.AUTHORIZATION); if (!headers.isEmpty()) { String auth = headers.get(0); if (auth.length() > 5) { String type = auth.substring(0, 5); type = type.toLowerCase(); if ("basic".equals(type)) { String cookie = auth.substring(6); cookie = new String(Base64.decodeBase64(cookie.getBytes())); String[] split = cookie.split(":"); Principal user = null; try { user = domain.authenticate(split[0], split[1]); return new VertxSecurityContext(user, domain, "BASIC", true); } catch (SecurityException e) { response.sendError(HttpResponseCodes.SC_UNAUTHORIZED); return null; } } else { response.sendError(HttpResponseCodes.SC_UNAUTHORIZED); return null; } } } return null; } }