org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jersey-server Show documentation
Show all versions of jersey-server Show documentation
Jersey core server implementation
/*
* Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.server.filter;
import java.io.IOException;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.annotation.Priority;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import org.glassfish.jersey.server.internal.LocalizationMessages;
import org.glassfish.jersey.server.model.AnnotatedMethod;
/**
* A {@link DynamicFeature} supporting the {@code javax.annotation.security.RolesAllowed},
* {@code javax.annotation.security.PermitAll} and {@code javax.annotation.security.DenyAll}
* on resource methods and sub-resource methods.
*
* The {@link javax.ws.rs.core.SecurityContext} is utilized, using the
* {@link javax.ws.rs.core.SecurityContext#isUserInRole(String) } method,
* to ascertain if the user is in one
* of the roles declared in by a {@code @RolesAllowed}. If a user is in none of
* the declared roles then a 403 (Forbidden) response is returned.
*
* If the {@code @DenyAll} annotation is declared then a 403 (Forbidden) response
* is returned.
*
* If the {@code @PermitAll} annotation is declared and is not overridden then
* this filter will not be applied.
*
* If a user is not authenticated and annotated method is restricted for certain roles then a 403
* (Not Authenticated) response is returned.
*
* @author Paul Sandoz
* @author Martin Matula
*/
public class RolesAllowedDynamicFeature implements DynamicFeature {
@Override
public void configure(final ResourceInfo resourceInfo, final FeatureContext configuration) {
final AnnotatedMethod am = new AnnotatedMethod(resourceInfo.getResourceMethod());
// DenyAll on the method take precedence over RolesAllowed and PermitAll
if (am.isAnnotationPresent(DenyAll.class)) {
configuration.register(new RolesAllowedRequestFilter());
return;
}
// RolesAllowed on the method takes precedence over PermitAll
RolesAllowed ra = am.getAnnotation(RolesAllowed.class);
if (ra != null) {
configuration.register(new RolesAllowedRequestFilter(ra.value()));
return;
}
// PermitAll takes precedence over RolesAllowed on the class
if (am.isAnnotationPresent(PermitAll.class)) {
// Do nothing.
return;
}
// DenyAll can't be attached to classes
// RolesAllowed on the class takes precedence over PermitAll
ra = resourceInfo.getResourceClass().getAnnotation(RolesAllowed.class);
if (ra != null) {
configuration.register(new RolesAllowedRequestFilter(ra.value()));
}
}
@Priority(Priorities.AUTHORIZATION) // authorization filter - should go after any authentication filters
private static class RolesAllowedRequestFilter implements ContainerRequestFilter {
private final boolean denyAll;
private final String[] rolesAllowed;
RolesAllowedRequestFilter() {
this.denyAll = true;
this.rolesAllowed = null;
}
RolesAllowedRequestFilter(final String[] rolesAllowed) {
this.denyAll = false;
this.rolesAllowed = (rolesAllowed != null) ? rolesAllowed : new String[] {};
}
@Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
if (!denyAll) {
if (rolesAllowed.length > 0 && !isAuthenticated(requestContext)) {
throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
}
for (final String role : rolesAllowed) {
if (requestContext.getSecurityContext().isUserInRole(role)) {
return;
}
}
}
throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
}
private static boolean isAuthenticated(final ContainerRequestContext requestContext) {
return requestContext.getSecurityContext().getUserPrincipal() != null;
}
}
}