You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2014/08/16 01:26:40 UTC

git commit: DELTASPIKE-637 prevent duplicated handling of AccessDeniedException

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 <gp...@apache.org>
Authored: Sat Aug 16 00:51:32 2014 +0200
Committer: gpetracek <gp...@apache.org>
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)