diff --git a/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhase.java b/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhase.java index b2185a2..1c6bea3 100644 --- a/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhase.java +++ b/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhase.java @@ -17,9 +17,6 @@ @Documented public @interface RestrictAtPhase { - public static PhaseIdType RESTRICT_INITIAL_DEFAULT = PhaseIdType.RENDER_RESPONSE; - public static PhaseIdType RESTRICT_POSTBACK_DEFAULT = PhaseIdType.INVOKE_APPLICATION; - - public PhaseIdType initial() default PhaseIdType.RENDER_RESPONSE; + public PhaseIdType initial() default PhaseIdType.RENDER_RESPONSE; // also stored as a static in ViewConfigSecurityEnforcer (impl) public PhaseIdType postback() default PhaseIdType.INVOKE_APPLICATION; } diff --git a/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhaseDefault.java b/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhaseDefault.java new file mode 100644 index 0000000..840caf3 --- /dev/null +++ b/api/src/main/java/org/jboss/seam/faces/view/config/RestrictAtPhaseDefault.java @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.jboss.seam.faces.view.config; + +import org.jboss.seam.faces.event.PhaseIdType; + +/** + * + * @author bleathem + */ +public class RestrictAtPhaseDefault +{ + public static final PhaseIdType RESTRICT_INITIAL_DEFAULT; + public static final PhaseIdType RESTRICT_POSTBACK_DEFAULT; + + static { + try { + RESTRICT_INITIAL_DEFAULT = (PhaseIdType) RestrictAtPhase.class.getMethod("initial").getDefaultValue(); + RESTRICT_POSTBACK_DEFAULT = (PhaseIdType) RestrictAtPhase.class.getMethod("postback").getDefaultValue(); + } catch (NoSuchMethodException ex) { + throw new IllegalStateException("Error initialising values", ex); + } catch (SecurityException ex) { + throw new IllegalStateException("Error initialising values", ex); + } + } +} diff --git a/impl/src/main/java/org/jboss/seam/faces/view/config/ViewConfigSecurityEnforcer.java b/impl/src/main/java/org/jboss/seam/faces/view/config/ViewConfigSecurityEnforcer.java index 5e9743f..901293d 100644 --- a/impl/src/main/java/org/jboss/seam/faces/view/config/ViewConfigSecurityEnforcer.java +++ b/impl/src/main/java/org/jboss/seam/faces/view/config/ViewConfigSecurityEnforcer.java @@ -1,13 +1,21 @@ package org.jboss.seam.faces.view.config; +import java.io.IOException; import java.lang.annotation.Annotation; import java.util.List; +import java.util.logging.Level; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; +import javax.faces.FacesException; +import javax.faces.application.NavigationHandler; import javax.faces.component.UIViewRoot; +import javax.faces.context.FacesContext; import javax.faces.event.AbortProcessingException; import javax.faces.event.PhaseEvent; import javax.inject.Inject; +import javax.security.auth.login.LoginException; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; import org.jboss.logging.Logger; import org.jboss.seam.faces.event.PhaseIdType; @@ -37,33 +45,30 @@ public class ViewConfigSecurityEnforcer public void observeRenderResponse(@Observes @Before @RenderResponse PhaseEvent event) { log.info("Before Render Response event"); - UIViewRoot viewRoot = (UIViewRoot) event.getFacesContext().getViewRoot(); - - if (isRestrictPhase(PhaseIdType.RENDER_RESPONSE, viewRoot.getViewId(), event.getFacesContext().isPostback())) - { - enforce(viewRoot); - } + performObservation(event, PhaseIdType.RENDER_RESPONSE); } public void observeInvokeApplication(@Observes @Before @InvokeApplication PhaseEvent event) { log.info("Before Render Response event"); - UIViewRoot viewRoot = (UIViewRoot) event.getFacesContext().getViewRoot(); - if (isRestrictPhase(PhaseIdType.INVOKE_APPLICATION, viewRoot.getViewId(), event.getFacesContext().isPostback())) - { - enforce(viewRoot); - } + performObservation(event, PhaseIdType.INVOKE_APPLICATION); } public void observeRestoreView(@Observes @After @RestoreView PhaseEvent event) { log.info("After Restore View event"); - UIViewRoot viewRoot = (UIViewRoot) event.getFacesContext().getViewRoot(); - if (isRestrictPhase(PhaseIdType.RESTORE_VIEW, viewRoot.getViewId(), event.getFacesContext().isPostback())) + performObservation(event, PhaseIdType.RESTORE_VIEW); + } + + private void performObservation(PhaseEvent event, PhaseIdType phaseIdType) + { + UIViewRoot viewRoot = (UIViewRoot) event.getFacesContext().getViewRoot(); + if (isRestrictPhase(phaseIdType, viewRoot.getViewId(), event.getFacesContext().isPostback())) { - enforce(viewRoot); + log.infof("Enforcing on phase %s", phaseIdType); + enforce(event.getFacesContext(), viewRoot); } - } + } public boolean isRestrictPhase(PhaseIdType currentPhase, String viewId, boolean isPostback) { @@ -71,16 +76,16 @@ public boolean isRestrictPhase(PhaseIdType currentPhase, String viewId, boolean PhaseIdType restrictAtPhaseType = null; if (restrictAtPhase != null) { - restrictAtPhaseType = isPostback ? restrictAtPhase.postback() : RestrictAtPhase.RESTRICT_INITIAL_DEFAULT; + restrictAtPhaseType = isPostback ? restrictAtPhase.postback() : restrictAtPhase.initial(); } if (restrictAtPhaseType == null) { - restrictAtPhaseType = isPostback ? RestrictAtPhase.RESTRICT_POSTBACK_DEFAULT : RestrictAtPhase.RESTRICT_INITIAL_DEFAULT; + restrictAtPhaseType = isPostback ? RestrictAtPhaseDefault.RESTRICT_POSTBACK_DEFAULT : RestrictAtPhaseDefault.RESTRICT_INITIAL_DEFAULT; } return restrictAtPhaseType.equals(currentPhase); } - private void enforce(UIViewRoot viewRoot) + private void enforce(FacesContext facesContext, UIViewRoot viewRoot) { List annotations = viewConfigStore.getAllQualifierData(viewRoot.getViewId(), SecurityBindingType.class); if (annotations == null || annotations.isEmpty()) @@ -92,8 +97,25 @@ private void enforce(UIViewRoot viewRoot) securityCheckEvent.fire(securityEvent); if (! securityEvent.isAuthorized()) { - throw new AbortProcessingException("Access denied"); + LoginView loginView = viewConfigStore.getAnnotationData(viewRoot.getViewId(), LoginView.class); + if (loginView == null || loginView.value() == null || loginView.value().isEmpty()) + { + facesContext.getExternalContext().setResponseStatus(401); + HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse(); + try { + response.sendError(401); + } catch (IOException ex) { + throw new FacesException("Error writing to HttpServlerResponse", ex); + } + facesContext.responseComplete(); + return; + } + String loginViewId = loginView.value(); + NavigationHandler navHandler = facesContext.getApplication().getNavigationHandler(); + navHandler.handleNavigation(facesContext, "", loginViewId); + facesContext.renderResponse(); + return; } - log.info("Access allowed"); + log.info("Access granted"); } }