В настоящее время я работаю с JAX-RS, в частности с Resteasy, потому что он «просто работает» с Wildfly, и мне не нужно ничего настраивать.Это действительно единственная причина, по которой я это использую.
Я уже реализовал базовую аутентификацию, рассчитывая заменить ее на OAuth2 позже, просто сделал это сейчас из соображений простоты.
Внешний вид ContainerRequestFilterвот так
@Provider
public class SecurityFilter implements ContainerRequestFilter {
private static final String AUTHORIZATION_HEADER_KEY = "Authorization";
private static final String AUTHORIZATION_HEADER_PREFIX = "Basic ";
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
if(isAuthenticated(containerRequestContext) == false)
containerRequestContext.abortWith(createUnauthorizedResponse("Access denied."));
}
private boolean isAuthenticated(ContainerRequestContext containerRequestContext) {
List<String> authHeader = containerRequestContext.getHeaders().get(AUTHORIZATION_HEADER_KEY);
ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) containerRequestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
Method method = methodInvoker.getMethod();
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
if (authHeader != null && authHeader.size() > 0) {
String authToken = authHeader.get(0).replaceFirst(AUTHORIZATION_HEADER_PREFIX, "");
byte[] decoded = null;
try {
decoded = Base64.getDecoder().decode(authToken);
} catch (IllegalArgumentException ex) {
return false;
}
String decodedString = new String(decoded);
StringTokenizer tokenizer = new StringTokenizer(decodedString, ":");
String username = null, password = null;
if(tokenizer.countTokens() < 2)
return false;
username = tokenizer.nextToken();
password = tokenizer.nextToken();
if (DbController.isValid(username, password, rolesAnnotation.value()))
return true;
}
return false;
}
private Response createUnauthorizedResponse(String msg) {
return Response.status(Response.Status.UNAUTHORIZED)
.entity("{ \"Unauthorized\" : \"" + msg + "\" }")
.type(MediaType.APPLICATION_JSON)
.build();
}
}
Отлично работает с почтальоном.И я понимаю, что основное использование таких API-интерфейсов есть и в других программах.
Но было бы неплохо, если бы при открытии в браузере он попросил бы вас ввести свои учетные данные, а не просто сказать, что выне авторизованы, без возможности реально ввести свои учетные данные.Если вы не сделаете какую-то хитрость, чтобы вручную поместить его в заголовок, но тогда вы могли бы также просто использовать почтальон.
Если я наложу ограничение безопасности на роль администратора с ограничением авторизации, оно выдаст диалог входа в систему, но затемавторизация не работает и просто продолжает запрашивать авторизацию.
Есть ли что-то еще, что я могу сделать вместо containerRequestContext.abortWith?Или мне нужно использовать совершенно другой подход, и он просто не будет работать с ContainerRequestFilter?