CCM NG: JavaDoc for the AuthorizationInterceptor and the supporting annotations

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3747 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2015-11-25 14:13:36 +00:00
parent a84c6ad626
commit bd56f40876
4 changed files with 70 additions and 12 deletions

View File

@ -31,9 +31,11 @@ import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor; import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext; import javax.interceptor.InvocationContext;
import org.libreccm.security.PermissionChecker;
/** /**
* A CDI interceptor which can be used to secure methods of CDI beans. To use
* the interceptor annotation the method to secure with
* {@link AuthorizationRequired} and one or more {@link RequiresRole} and/or
* {@link RequiresPrivilege} annotations.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@ -41,37 +43,68 @@ import org.libreccm.security.PermissionChecker;
@Interceptor @Interceptor
public class AuthorizationInterceptor { public class AuthorizationInterceptor {
/**
* A logger for providing some informations what the interceptor is doing.
*/
private static final Logger LOGGER = LogManager.getLogger( private static final Logger LOGGER = LogManager.getLogger(
AuthorizationInterceptor.class); AuthorizationInterceptor.class);
/**
* The current subject
*/
@Inject @Inject
private Subject subject; private Subject subject;
/**
* An instance of the {@link PermissionChecker} bean. The interceptor uses
* the methods of the {@code PermissionChecker} class to check if the
* current subject has the required roles and permissions.
*/
@Inject @Inject
private PermissionChecker permissionChecker; private PermissionChecker permissionChecker;
/**
* Called by the CDI container when a method annotated with
* {@link AuthorizationRequired} is called.
*
* @param context The invocation context of the method.
*
* @return The return value of the called method.
*
* @throws Exception If any exception occurs.
*/
@AroundInvoke @AroundInvoke
public Object intercept(final InvocationContext context) throws Exception { public Object intercept(final InvocationContext context) throws Exception {
LOGGER.debug("Intercepting method invocation"); LOGGER.debug("Intercepting method invocation");
//Get the method which call was intercepted.
final Method method = context.getMethod(); final Method method = context.getMethod();
if (method == null) { if (method == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The authoriziation interceptor can only be used for method"); "The authoriziation interceptor can only be used for method");
} }
// Check if the method has a RequiresRole annotation. If yes, check
// if the current subject is assigned to the required role.
if (method.isAnnotationPresent(RequiresRole.class)) { if (method.isAnnotationPresent(RequiresRole.class)) {
final String requiredRole = method.getAnnotation(RequiresRole.class) final String requiredRole = method.getAnnotation(RequiresRole.class)
.value(); .value();
subject.checkRoles(requiredRole); subject.checkRoles(requiredRole);
} }
// Check if the RequiresPrivilege annotation is present on the
// method level. If yes check if the current subject has a permission
// granting the required privilege.
if (method.isAnnotationPresent(RequiresPrivilege.class)) { if (method.isAnnotationPresent(RequiresPrivilege.class)) {
final String requiredPrivilege = method.getAnnotation( final String requiredPrivilege = method.getAnnotation(
RequiresPrivilege.class).value(); RequiresPrivilege.class).value();
permissionChecker.checkPermission(requiredPrivilege); permissionChecker.checkPermission(requiredPrivilege);
} }
// Check if one or more parameters are annotated with the
// RequiredPrivilege annotation. If yes check if the parameter is
// of type CcmObject and check if the current subject has a permission
// granting the required privilege on the provided CcmObject instance.
final Annotation[][] annotations = method.getParameterAnnotations(); final Annotation[][] annotations = method.getParameterAnnotations();
final Object[] parameters = context.getParameters(); final Object[] parameters = context.getParameters();
if (parameters != null && parameters.length > 0 if (parameters != null && parameters.length > 0
@ -84,15 +117,21 @@ public class AuthorizationInterceptor {
return context.proceed(); return context.proceed();
} }
/**
* Helper method for checking the parameter permissions.
*
* @param parameter The parameter to check.
* @param annotations All annotations of the parameter.
*/
private void checkParameterPermission(final Object parameter, private void checkParameterPermission(final Object parameter,
final Annotation[] annotations) { final Annotation[] annotations) {
if (parameter instanceof CcmObject if (parameter instanceof CcmObject
&& annotations != null && annotations != null
&& annotations.length > 0) { && annotations.length > 0) {
final CcmObject object = (CcmObject) parameter; final CcmObject object = (CcmObject) parameter;
String requiredPrivilege = null; String requiredPrivilege = null;
for(Annotation annotation : annotations) { for (Annotation annotation : annotations) {
if (annotation instanceof RequiresPrivilege) { if (annotation instanceof RequiresPrivilege) {
requiredPrivilege = ((RequiresPrivilege) annotation).value(); requiredPrivilege = ((RequiresPrivilege) annotation).value();
break; break;

View File

@ -27,6 +27,8 @@ import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding; import javax.interceptor.InterceptorBinding;
/** /**
* Use this annotation to secure a method by the
* {@link AuthorizationInterceptor}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */

View File

@ -18,6 +18,8 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.core.CcmObject;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited; import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -25,6 +27,17 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* This annotation is used together with the {@link AuthorizationRequired}
* annotation to limit access to methods based on the permissions granted to a
* user. The annotation can be used to annotation an method or a parameter of
* the type {@link CcmObject}.
*
* If used on the method level the current subject must have a permission
* granting the privilege provided by this annotation to call the method.
*
* If used on a parameter of type {@link CcmObject} the current subject must
* have a permission granting the privilege provided by this annotation for the
* particular instance of {@code CcmObject}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */

View File

@ -25,6 +25,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* This annotation is used together with the {@link AuthorizationRequired}
* annotation to limit access to methods based on the roles assigned to a user.
* To call a method annotation with this annotation the current subject must be
* assigned to the role provided by this annotation.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */