[New] Implemented Basic authentication for REST APIs
This commit is contained in:
parent
984f6bff41
commit
0481ecc90d
|
@ -26,7 +26,8 @@ import javax.ws.rs.container.ContainerRequestContext;
|
||||||
import javax.ws.rs.container.ContainerRequestFilter;
|
import javax.ws.rs.container.ContainerRequestFilter;
|
||||||
import javax.ws.rs.core.*;
|
import javax.ws.rs.core.*;
|
||||||
import javax.ws.rs.ext.Provider;
|
import javax.ws.rs.ext.Provider;
|
||||||
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -34,6 +35,7 @@ import java.util.Set;
|
||||||
import li.strolch.exception.StrolchAccessDeniedException;
|
import li.strolch.exception.StrolchAccessDeniedException;
|
||||||
import li.strolch.exception.StrolchNotAuthenticatedException;
|
import li.strolch.exception.StrolchNotAuthenticatedException;
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
|
import li.strolch.privilege.model.Usage;
|
||||||
import li.strolch.rest.RestfulStrolchComponent;
|
import li.strolch.rest.RestfulStrolchComponent;
|
||||||
import li.strolch.rest.StrolchRestfulConstants;
|
import li.strolch.rest.StrolchRestfulConstants;
|
||||||
import li.strolch.rest.StrolchSessionHandler;
|
import li.strolch.rest.StrolchSessionHandler;
|
||||||
|
@ -103,7 +105,7 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filter(ContainerRequestContext requestContext) throws IOException {
|
public void filter(ContainerRequestContext requestContext) {
|
||||||
String remoteIp = getRemoteIp(this.request);
|
String remoteIp = getRemoteIp(this.request);
|
||||||
logger.info("Remote IP: " + remoteIp + ": " + requestContext.getMethod() + " " + requestContext.getUriInfo()
|
logger.info("Remote IP: " + remoteIp + ": " + requestContext.getMethod() + " " + requestContext.getUriInfo()
|
||||||
.getRequestUri());
|
.getRequestUri());
|
||||||
|
@ -152,8 +154,8 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
|
||||||
*/
|
*/
|
||||||
protected Certificate validateSession(ContainerRequestContext requestContext, String remoteIp) {
|
protected Certificate validateSession(ContainerRequestContext requestContext, String remoteIp) {
|
||||||
|
|
||||||
String sessionId = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
|
String authorization = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
|
||||||
if (StringHelper.isEmpty(sessionId)) {
|
if (StringHelper.isEmpty(authorization)) {
|
||||||
|
|
||||||
Cookie cookie = requestContext.getCookies().get(StrolchRestfulConstants.STROLCH_AUTHORIZATION);
|
Cookie cookie = requestContext.getCookies().get(StrolchRestfulConstants.STROLCH_AUTHORIZATION);
|
||||||
if (cookie == null) {
|
if (cookie == null) {
|
||||||
|
@ -166,7 +168,7 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionId = cookie.getValue();
|
String sessionId = cookie.getValue();
|
||||||
if (StringHelper.isEmpty(sessionId)) {
|
if (StringHelper.isEmpty(sessionId)) {
|
||||||
logger.error("Authorization Cookie value missing on request to URL " + requestContext.getUriInfo()
|
logger.error("Authorization Cookie value missing on request to URL " + requestContext.getUriInfo()
|
||||||
.getPath());
|
.getPath());
|
||||||
|
@ -176,11 +178,34 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
|
||||||
.build());
|
.build());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return validateCertificate(requestContext, sessionId, remoteIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance()
|
authorization = authorization.trim();
|
||||||
.getComponent(StrolchSessionHandler.class);
|
if (authorization.startsWith("Basic ")) {
|
||||||
Certificate certificate = sessionHandler.validate(sessionId, remoteIp);
|
return authenticateBasic(requestContext, authorization, remoteIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validateCertificate(requestContext, authorization, remoteIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Certificate authenticateBasic(ContainerRequestContext requestContext, String authorization,
|
||||||
|
String remoteIp) {
|
||||||
|
String basicAuth = authorization.substring("Basic ".length());
|
||||||
|
basicAuth = new String(Base64.getDecoder().decode(basicAuth.getBytes()), StandardCharsets.UTF_8);
|
||||||
|
String[] parts = basicAuth.split(":");
|
||||||
|
if (parts.length != 2) {
|
||||||
|
requestContext.abortWith(
|
||||||
|
Response.status(Response.Status.BAD_REQUEST).header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
|
||||||
|
.entity("Invalid Basic Authorization!") //$NON-NLS-1$
|
||||||
|
.build());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Performing basic auth for user " + parts[0] + "...");
|
||||||
|
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler();
|
||||||
|
Certificate certificate = sessionHandler.authenticate(parts[0], parts[1].toCharArray(), remoteIp, Usage.SINGLE);
|
||||||
|
|
||||||
requestContext.setProperty(STROLCH_CERTIFICATE, certificate);
|
requestContext.setProperty(STROLCH_CERTIFICATE, certificate);
|
||||||
requestContext.setProperty(STROLCH_REQUEST_SOURCE, remoteIp);
|
requestContext.setProperty(STROLCH_REQUEST_SOURCE, remoteIp);
|
||||||
|
@ -188,6 +213,15 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
|
||||||
return certificate;
|
return certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Certificate validateCertificate(ContainerRequestContext requestContext, String sessionId, String remoteIp) {
|
||||||
|
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler();
|
||||||
|
Certificate certificate = sessionHandler.validate(sessionId, remoteIp);
|
||||||
|
|
||||||
|
requestContext.setProperty(STROLCH_CERTIFICATE, certificate);
|
||||||
|
requestContext.setProperty(STROLCH_REQUEST_SOURCE, remoteIp);
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getRemoteIp(HttpServletRequest request) {
|
public static String getRemoteIp(HttpServletRequest request) {
|
||||||
|
|
||||||
String remoteHost = request.getRemoteHost();
|
String remoteHost = request.getRemoteHost();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
|
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -17,15 +17,16 @@ package li.strolch.rest.filters;
|
||||||
|
|
||||||
import static li.strolch.rest.StrolchRestfulConstants.STROLCH_CERTIFICATE;
|
import static li.strolch.rest.StrolchRestfulConstants.STROLCH_CERTIFICATE;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.ws.rs.container.ContainerRequestContext;
|
import javax.ws.rs.container.ContainerRequestContext;
|
||||||
import javax.ws.rs.container.ContainerResponseContext;
|
import javax.ws.rs.container.ContainerResponseContext;
|
||||||
import javax.ws.rs.container.ContainerResponseFilter;
|
import javax.ws.rs.container.ContainerResponseFilter;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.ext.Provider;
|
import javax.ws.rs.ext.Provider;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
|
import li.strolch.rest.RestfulStrolchComponent;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Reto Breitenmoser <reto.breitenmoser@4trees.ch>
|
* @author Reto Breitenmoser <reto.breitenmoser@4trees.ch>
|
||||||
|
@ -34,13 +35,19 @@ import li.strolch.privilege.model.Certificate;
|
||||||
@Provider
|
@Provider
|
||||||
public class AuthenticationResponseFilter implements ContainerResponseFilter {
|
public class AuthenticationResponseFilter implements ContainerResponseFilter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AuthenticationResponseFilter.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
|
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
Certificate cert = (Certificate) requestContext.getProperty(STROLCH_CERTIFICATE);
|
Certificate cert = (Certificate) requestContext.getProperty(STROLCH_CERTIFICATE);
|
||||||
if (cert != null) {
|
if (cert == null)
|
||||||
responseContext.getHeaders().add(HttpHeaders.AUTHORIZATION, cert.getAuthToken());
|
return;
|
||||||
|
|
||||||
|
if (cert.getUsage().isSingle()) {
|
||||||
|
logger.info("Invalidating single usage certificate for " + cert.getUsername());
|
||||||
|
RestfulStrolchComponent.getInstance().getSessionHandler().invalidate(cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue