package restx.security; import com.google.common.base.Charsets; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import com.google.common.io.BaseEncoding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import restx.*; import restx.factory.Component; import restx.http.HttpStatus; import javax.inject.Inject; import java.io.IOException; import java.util.Locale; /** * Date: 16/12/13 * Time: 22:29 */ @Component(priority = -190) public class HttpAuthenticationFilter implements RestxFilter { private static final Logger logger = LoggerFactory.getLogger(HttpAuthenticationFilter.class); private HttpBasicAuthHandler basicHandler; public HttpAuthenticationFilter(HttpBasicAuthHandler basicHandler) { this.basicHandler = basicHandler; } @Override public Optional<RestxHandlerMatch> match(RestxRequest req) { Optional<String> authorization = req.getHeader("Authorization"); if (authorization.isPresent()) { if (authorization.get().toLowerCase(Locale.ENGLISH).startsWith("basic ")) { return Optional.of(new RestxHandlerMatch( new StdRestxRequestMatch("*", req.getRestxPath()), basicHandler)); } else { logger.warn("unsupported authentication type: " + authorization.get()); } } return Optional.absent(); } @Override public String toString() { return "HttpAuthenticationFilter"; } @Component public static class HttpBasicAuthHandler implements RestxHandler { private final BasicPrincipalAuthenticator authenticator; public HttpBasicAuthHandler(BasicPrincipalAuthenticator authenticator) { this.authenticator = authenticator; } @Override public void handle(RestxRequestMatch match, RestxRequest req, RestxResponse resp, RestxContext ctx) throws IOException { String base64Pwd = req.getHeader("Authorization").get().substring("basic ".length()); String auth = new String(BaseEncoding.base64().decode(base64Pwd), Charsets.UTF_8); int i = auth.indexOf(':'); if (i < 0) { throw new WebException(HttpStatus.BAD_REQUEST, "Invalid Basic Authentication. It must have the form <user>:<pwd>. It was: " + auth); } String u = auth.substring(0, i); String pwd = auth.substring(i + 1); Optional<? extends RestxPrincipal> principal = authenticator.authenticate( u, pwd, ImmutableMap.<String, Object>of()); if (principal.isPresent()) { logger.debug("http basic authenticated '{}'", principal.get().getName()); RestxSession.current().authenticateAs(principal.get()); } else { throw new WebException(HttpStatus.UNAUTHORIZED); } ctx.nextHandlerMatch().handle(req, resp, ctx); } @Override public String toString() { return "HttpBasicAuthHandler"; } } }