Repository: deltaspike Updated Branches: refs/heads/master 72bbb515b -> 3f14b9411
DELTASPIKE-637 prevent duplicated handling of AccessDeniedException Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/3f14b941 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/3f14b941 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/3f14b941 Branch: refs/heads/master Commit: 3f14b941154ac59edbb04fb0e77e21ade712ae19 Parents: 72bbb51 Author: gpetracek <[email protected]> Authored: Sat Aug 16 00:51:32 2014 +0200 Committer: gpetracek <[email protected]> Committed: Sat Aug 16 01:17:32 2014 +0200 ---------------------------------------------------------------------- .../control/BridgeExceptionHandlerWrapper.java | 70 ++++++++++++++------ .../AccessDeniedExceptionBroadcaster.java | 52 +++++++++++++++ .../impl/security/SecurityAwareViewHandler.java | 16 +++++ .../deltaspike/jsf/impl/util/JsfUtils.java | 16 ++++- 4 files changed, 132 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3f14b941/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/exception/control/BridgeExceptionHandlerWrapper.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/exception/control/BridgeExceptionHandlerWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/exception/control/BridgeExceptionHandlerWrapper.java index 8453007..03b7557 100644 --- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/exception/control/BridgeExceptionHandlerWrapper.java +++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/exception/control/BridgeExceptionHandlerWrapper.java @@ -19,9 +19,7 @@ package org.apache.deltaspike.jsf.impl.exception.control; import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; import java.util.Iterator; -import javax.el.ELException; import javax.enterprise.inject.spi.BeanManager; import javax.faces.FacesException; import javax.faces.context.ExceptionHandler; @@ -32,8 +30,13 @@ import javax.faces.event.ExceptionQueuedEvent; import javax.faces.event.PhaseId; import javax.faces.event.SystemEvent; +import org.apache.deltaspike.core.api.config.view.DefaultErrorView; import org.apache.deltaspike.core.api.exception.control.event.ExceptionToCatchEvent; import org.apache.deltaspike.core.spi.activation.Deactivatable; +import org.apache.deltaspike.jsf.impl.util.JsfUtils; +import org.apache.deltaspike.jsf.impl.util.SecurityUtils; +import org.apache.deltaspike.security.api.authorization.AccessDeniedException; +import org.apache.deltaspike.security.api.authorization.ErrorViewAwareAccessDeniedException; public class BridgeExceptionHandlerWrapper extends ExceptionHandlerWrapper implements Deactivatable { @@ -76,14 +79,23 @@ public class BridgeExceptionHandlerWrapper extends ExceptionHandlerWrapper imple Throwable throwable = iterator.next().getContext().getException(); Throwable rootCause = getRootCause(throwable); - ExceptionToCatchEvent event = new ExceptionToCatchEvent(rootCause, exceptionQualifier); - event.setOptional(true); - - beanManager.fireEvent(event); - - if (event.isHandled()) + if (rootCause instanceof AccessDeniedException) { + processAccessDeniedException(rootCause); iterator.remove(); + continue; + } + else + { + ExceptionToCatchEvent event = new ExceptionToCatchEvent(rootCause, exceptionQualifier); + event.setOptional(true); + + beanManager.fireEvent(event); + + if (event.isHandled()) + { + iterator.remove(); + } } // a handle method might redirect and set responseComplete @@ -100,13 +112,7 @@ public class BridgeExceptionHandlerWrapper extends ExceptionHandlerWrapper imple @Override public Throwable getRootCause(Throwable throwable) { - while ((ELException.class.isInstance(throwable) || FacesException.class.isInstance(throwable) || - InvocationTargetException.class.isInstance(throwable)) && throwable.getCause() != null) - { - throwable = throwable.getCause(); - } - - return throwable; + return JsfUtils.getRootCause(throwable); } @Override @@ -124,17 +130,39 @@ public class BridgeExceptionHandlerWrapper extends ExceptionHandlerWrapper imple { Throwable exception = getRootCause(exceptionQueuedEvent.getContext().getException()); - ExceptionToCatchEvent exceptionToCatchEvent = new ExceptionToCatchEvent(exception); - exceptionToCatchEvent.setOptional(true); + if (exception instanceof AccessDeniedException) + { + processAccessDeniedException(exception); + } + else + { + ExceptionToCatchEvent exceptionToCatchEvent = new ExceptionToCatchEvent(exception); + exceptionToCatchEvent.setOptional(true); - this.beanManager.fireEvent(exceptionToCatchEvent); + this.beanManager.fireEvent(exceptionToCatchEvent); - if (exceptionToCatchEvent.isHandled()) - { - return; + if (exceptionToCatchEvent.isHandled()) + { + return; + } } } } super.processEvent(event); } + + private void processAccessDeniedException(Throwable throwable) + { + if (throwable instanceof ErrorViewAwareAccessDeniedException) + { + SecurityUtils.handleSecurityViolationWithoutNavigation((AccessDeniedException) throwable); + } + else + { + ErrorViewAwareAccessDeniedException securityException = + new ErrorViewAwareAccessDeniedException( + ((AccessDeniedException)throwable).getViolations(), DefaultErrorView.class); + SecurityUtils.handleSecurityViolationWithoutNavigation(securityException); + } + } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3f14b941/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/AccessDeniedExceptionBroadcaster.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/AccessDeniedExceptionBroadcaster.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/AccessDeniedExceptionBroadcaster.java new file mode 100644 index 0000000..4957d0e --- /dev/null +++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/AccessDeniedExceptionBroadcaster.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.jsf.impl.security; + +import org.apache.deltaspike.core.api.exception.control.event.ExceptionToCatchEvent; +import org.apache.deltaspike.security.api.authorization.AccessDeniedException; + +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; + +//allows to customize the default handling +@Dependent +public class AccessDeniedExceptionBroadcaster +{ + @Inject + private BeanManager beanManager; + + public Throwable broadcastAccessDeniedException(AccessDeniedException accessDeniedException) + { + ExceptionToCatchEvent exceptionToCatchEvent = new ExceptionToCatchEvent(accessDeniedException); + + try + { + this.beanManager.fireEvent(exceptionToCatchEvent); + } + catch (AccessDeniedException e) + { + //intentionally ignore the exception per default, since we just notify the handlers + //(like in the other cases with AccessDeniedException) + //that's different from the normal exception-control handling + return null; + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3f14b941/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/SecurityAwareViewHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/SecurityAwareViewHandler.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/SecurityAwareViewHandler.java index 2d369b0..0ada120 100644 --- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/SecurityAwareViewHandler.java +++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/security/SecurityAwareViewHandler.java @@ -24,6 +24,7 @@ import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver; import org.apache.deltaspike.core.api.provider.BeanProvider; import org.apache.deltaspike.core.spi.activation.Deactivatable; import org.apache.deltaspike.core.util.ClassDeactivationUtils; +import org.apache.deltaspike.core.util.ExceptionUtils; import org.apache.deltaspike.jsf.api.config.JsfModuleConfig; import org.apache.deltaspike.jsf.api.config.view.View; import org.apache.deltaspike.jsf.impl.util.SecurityUtils; @@ -134,6 +135,8 @@ public class SecurityAwareViewHandler extends ViewHandlerWrapper implements Deac errorView = SecurityUtils.handleSecurityViolationWithoutNavigation(accessDeniedException); } + broadcastAccessDeniedException(accessDeniedException); + return this.wrapped.createView(context, viewConfigResolver.getViewConfigDescriptor(errorView).getViewId()); } finally @@ -152,6 +155,19 @@ public class SecurityAwareViewHandler extends ViewHandlerWrapper implements Deac return result; } + protected void broadcastAccessDeniedException(ErrorViewAwareAccessDeniedException accessDeniedException) + { + AccessDeniedExceptionBroadcaster exceptionBroadcaster = + BeanProvider.getContextualReference(AccessDeniedExceptionBroadcaster.class); + + Throwable broadcastResult = exceptionBroadcaster.broadcastAccessDeniedException(accessDeniedException); + + if (broadcastResult != null) + { + throw ExceptionUtils.throwAsRuntimeException(broadcastResult); + } + } + private synchronized void lazyInit() { this.securityModuleActivated = http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3f14b941/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java index fd1afaa..7b1dabf 100644 --- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java +++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java @@ -25,11 +25,14 @@ import org.apache.deltaspike.jsf.api.config.JsfModuleConfig; import org.apache.deltaspike.jsf.impl.listener.phase.WindowMetaData; import org.apache.deltaspike.jsf.impl.message.FacesMessageEntry; +import javax.el.ELException; import javax.enterprise.context.ContextNotActiveException; +import javax.faces.FacesException; import javax.faces.application.FacesMessage; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashSet; @@ -41,7 +44,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public abstract class JsfUtils { private static final String SB_ADD_PARAMETER = "SB:" + JsfUtils.class + "#addParameter"; - + public static <T> T getValueOfExpression(String expression, Class<T> targetType) { FacesContext facesContext = FacesContext.getCurrentInstance(); @@ -323,6 +326,17 @@ public abstract class JsfUtils } } + public static Throwable getRootCause(Throwable throwable) + { + while ((ELException.class.isInstance(throwable) || FacesException.class.isInstance(throwable) || + InvocationTargetException.class.isInstance(throwable)) && throwable.getCause() != null) + { + throwable = throwable.getCause(); + } + + return throwable; + } + public static boolean isNewMessage(List<FacesMessage> facesMessages, FacesMessage messageToCheck) { for (FacesMessage facesMessage : facesMessages)
