Announcement Announcement Module
Collapse
No announcement yet.
Acegi Security System in Spring WebFlow Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #31
    next question...if i log in with a user that does not have the necessary role...ie secure-flow=ROLE_USER and this user only has ROLE_FOOBAR instead of redirecting to my access denied page i get redirected to a tomcat exception page...

    Exception thrown in state 'null' of flow 'secure-flow'; nested exception is java.lang.IllegalStateException: This flow execution is not active, it has either ended or has never been started.

    is there a quick answer...or should i add a simpleMappingExceptionResolver

    Comment


    • #32
      The acegi security configuration i actually use works perfect for URLS that use simple MVC controllers. But does not seem to work for webflow. When i look at the stack trace it seems to be calling the filters in the chain, but httpsessionintegrationfilter does not seem to bring up the login page to be able to authethicate the user. I tried it with methodsecurityinterceptor and gives me similar problems. AuthenticationCredentialsNotFoundException.

      Comment


      • #33
        have you included swf-93?

        are you using one servlet or multiple servlets?

        for instance I am using one servlet mapped to /rfsportal.rfs which means the straight acegi security configuration only needs to use that one url for the filter.

        It also means that my flow/state/event security has to be defined in the **-servlet.xml file as a flow securityinterceptor which is really a flowListener.

        Comment


        • #34
          next question...if i log in with a user that does not have the necessary role...ie secure-flow=ROLE_USER and this user only has ROLE_FOOBAR instead of redirecting to my access denied page i get redirected to a tomcat exception page...

          Exception thrown in state 'null' of flow 'secure-flow'; nested exception is java.lang.IllegalStateException: This flow execution is not active, it has either ended or has never been started.

          is there a quick answer...or should i add a simpleMappingExceptionResolver
          I beleive there is an issue with the ExceptionTranslating, but need to investigate a bit more. IMHO it doesn't translate/notice the nested exception when there is a FlowException in the chain... Might have something to do with the super class of that exception...

          Comment


          • #35
            i seem to remember something about when its a webflow exception, the exception cant be handled within webflow.

            which would explain why adding a the handler in the *-servlet.xml file works.

            Comment


            • #36
              Originally posted by trdyer View Post
              have you included swf-93?

              are you using one servlet or multiple servlets?

              for instance I am using one servlet mapped to /rfsportal.rfs which means the straight acegi security configuration only needs to use that one url for the filter.

              It also means that my flow/state/event security has to be defined in the **-servlet.xml file as a flow securityinterceptor which is really a flowListener.
              Yes, I have included SWF-93, and I am only using one url? flow.htm?_flowId=requestpassword-weflow. Strangely enough, i have the same problem with methodsecurityinterceptor, does not find authentication object inside the securitycontext.

              Comment


              • #37
                is acegi authenticating you?

                Comment


                • #38
                  When i use regular mvc controller, and the is the url is listed as secure, it will display the login page to authenticate the user. This does not seem to be the case when using methodsecurityinterceptor or flowsecurityinterceptor, which configuration is almost similar. The only difference between these interceptors and filtersecurityinterceptor, is that the latter is a filter and part of the filter chain. Can this be the issue?

                  Any help would be appreciated.

                  Comment


                  • #39
                    If you look at the code of the ExceptionTranslationFilter it checks if a thrown exception is

                    * AuthenticationException
                    * AccessDeniedException
                    * ServletException (when this is the cause it looks at the rootCause to be one of the above exceptions)

                    Problem with the method and flow security stuff is that the original exception (AuthenticationException or AccessDeniedException) gets wrapped inside another exception. So it falls through the checks and simply gets thrown.

                    Comment


                    • #40
                      you mean the former is a part of the filter chain....right?


                      so if you dont login anywhere you arent getting the user in the securitycontextholder? that seems like the correct behaviour to me.

                      have you defined the flowsecuritylistener and added it it to the flow executor?

                      ********

                      I saw there was a JIRA issue on that requesting a better strategy for unwrapping exceptions...seems like there hasnt been any movement on it.
                      Last edited by trdyer; Nov 7th, 2007, 08:22 AM.

                      Comment


                      • #41
                        I saw there was a JIRA issue on that requesting a better strategy for unwrapping exceptions...seems like there hasnt been any movement on it.
                        Well creating a patch shouldn't be that hard. I'll give the code a bit of a look.

                        Comment


                        • #42
                          yeah, im thinking i may do the same

                          Comment


                          • #43
                            Code:
                            public class ExceptionTranslationFilter implements Filter, InitializingBean {
                               // ~ Static fields/initializers
                               // =====================================================================================
                            
                               private static final Log logger = LogFactory.getLog(ExceptionTranslationFilter.class);
                            
                               // ~ Instance fields
                               // ================================================================================================
                            
                               private AccessDeniedHandler accessDeniedHandler;
                            
                               private AuthenticationEntryPoint authenticationEntryPoint;
                            
                               private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
                            
                               private PortResolver portResolver = new PortResolverImpl();
                            
                               private boolean createSessionAllowed = true;
                            
                               // ~ Methods
                               // ========================================================================================================
                            
                               public void afterPropertiesSet() throws Exception {
                                   Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint must be specified");
                                   Assert.notNull(portResolver, "portResolver must be specified");
                                   Assert.notNull(authenticationTrustResolver, "authenticationTrustResolver must be specified");
                               }
                            
                               /**
                                * Introspects the <code>Applicationcontext</code> for the single instance
                                * of {@link AccessDeniedHandler}. If found invoke
                                * setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler) method by
                                * providing the found instance of accessDeniedHandler as a method
                                * parameter. If more than one instance of <code>AccessDeniedHandler</code>
                                * is found, the method throws <code>IllegalStateException</code>.
                                * 
                                * @param applicationContext to locate the instance
                                */
                               private void autoDetectAnyAccessDeniedHandlerAndUseIt(ApplicationContext applicationContext) {
                                   Map map = applicationContext.getBeansOfType(AccessDeniedHandler.class);
                                   if (map.size() > 1) {
                                       throw new IllegalArgumentException(
                                               "More than one AccessDeniedHandler beans detected please refer to the one using "
                                                       + " [ accessDeniedBeanRef  ] " + "attribute");
                                   }
                                   else if (map.size() == 1) {
                                       AccessDeniedHandler handler = (AccessDeniedHandlerImpl) map.values().iterator().next();
                                       setAccessDeniedHandler(handler);
                                   }
                                   else {
                                       // create and use the default one specified as an instance variable.
                                       accessDeniedHandler = new AccessDeniedHandlerImpl();
                                   }
                            
                               }
                            
                               public void destroy() {
                               }
                            
                               public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
                                       ServletException {
                                   if (!(request instanceof HttpServletRequest)) {
                                       throw new ServletException("HttpServletRequest required");
                                   }
                            
                                   if (!(response instanceof HttpServletResponse)) {
                                       throw new ServletException("HttpServletResponse required");
                                   }
                            
                                   try {
                                       chain.doFilter(request, response);
                            
                                       if (logger.isDebugEnabled()) {
                                           logger.debug("Chain processed normally");
                                       }
                                   }
                                   catch (AuthenticationException ex) {
                                       handleException(request, response, chain, ex);
                                   }
                                   catch (AccessDeniedException ex) {
                                       handleException(request, response, chain, ex);
                                   } catch (IOException ex) {
                                       throw ex;
                                   }
                                   catch (Exception ex) {
                                       AcegiSecurityException aex = getAcegiSecurityException(ex);
                                       if (aex != null) {
                                           handleException(request, response, chain, (AcegiSecurityException) aex);
                                       } else {
                                           throw new ServletException(ex);
                                       }
                                   }
                               }
                            
                               AcegiSecurityException getAcegiSecurityException(Exception e) {
                                   if (e instanceof IOException) {
                                       return null;
                                   }
                                   
                                   AcegiSecurityException ase = null;
                                   
                                   Throwable t = e;
                                   while (ase == null && t != null) {
                                       if (t instanceof AccessDeniedException || t instanceof AuthenticationException) {
                                           ase = (AcegiSecurityException) t;
                                       }
                                       t = t.getCause();
                                   }
                                   return ase;
                               }
                               
                               public AuthenticationEntryPoint getAuthenticationEntryPoint() {
                                   return authenticationEntryPoint;
                               }
                            
                               public AuthenticationTrustResolver getAuthenticationTrustResolver() {
                                   return authenticationTrustResolver;
                               }
                            
                               public PortResolver getPortResolver() {
                                   return portResolver;
                               }
                            
                               private void handleException(ServletRequest request, ServletResponse response, FilterChain chain,
                                       AcegiSecurityException exception) throws IOException, ServletException {
                                   if (exception instanceof AuthenticationException) {
                                       if (logger.isDebugEnabled()) {
                                           logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception);
                                       }
                            
                                       sendStartAuthentication(request, response, chain, (AuthenticationException) exception);
                                   }
                                   else if (exception instanceof AccessDeniedException) {
                                       if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
                                           if (logger.isDebugEnabled()) {
                                               logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point",
                                                       exception);
                                           }
                            
                                           sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException(
                                                   "Full authentication is required to access this resource"));
                                       }
                                       else {
                                           if (logger.isDebugEnabled()) {
                                               logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
                                                       exception);
                                           }
                            
                                           accessDeniedHandler.handle(request, response, (AccessDeniedException) exception);
                                       }
                                   }
                               }
                            
                               public void init(FilterConfig filterConfig) throws ServletException {
                               }
                            
                               /**
                                * If <code>true</code>, indicates that
                                * <code>SecurityEnforcementFilter</code> is permitted to store the target
                                * URL and exception information in the <code>HttpSession</code> (the
                                * default). In situations where you do not wish to unnecessarily create
                                * <code>HttpSession</code>s - because the user agent will know the
                                * failed URL, such as with BASIC or Digest authentication - you may wish to
                                * set this property to <code>false</code>. Remember to also set the
                                * {@link org.acegisecurity.context.HttpSessionContextIntegrationFilter#allowSessionCreation}
                                * to <code>false</code> if you set this property to <code>false</code>.
                                * 
                                * @return <code>true</code> if the <code>HttpSession</code> will be
                                * used to store information about the failed request, <code>false</code>
                                * if the <code>HttpSession</code> will not be used
                                */
                               public boolean isCreateSessionAllowed() {
                                   return createSessionAllowed;
                               }
                            
                               protected void sendStartAuthentication(ServletRequest request, ServletResponse response, FilterChain chain,
                                       AuthenticationException reason) throws ServletException, IOException {
                                   HttpServletRequest httpRequest = (HttpServletRequest) request;
                            
                                   SavedRequest savedRequest = new SavedRequest(httpRequest, portResolver);
                            
                                   if (logger.isDebugEnabled()) {
                                       logger.debug("Authentication entry point being called; SavedRequest added to Session: " + savedRequest);
                                   }
                            
                                   if (createSessionAllowed) {
                                       // Store the HTTP request itself. Used by AbstractProcessingFilter
                                       // for redirection after successful authentication (SEC-29)
                                       httpRequest.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY, savedRequest);
                                   }
                            
                                   // SEC-112: Clear the SecurityContextHolder's Authentication, as the
                                   // existing Authentication is no longer considered valid
                                   SecurityContextHolder.getContext().setAuthentication(null);
                            
                                   authenticationEntryPoint.commence(httpRequest, (HttpServletResponse) response, reason);
                               }
                            
                               public void setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler) {
                                   Assert.notNull(accessDeniedHandler, "AccessDeniedHandler required");
                                   this.accessDeniedHandler = accessDeniedHandler;
                               }
                            
                               public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
                                   this.authenticationEntryPoint = authenticationEntryPoint;
                               }
                            
                               public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
                                   this.authenticationTrustResolver = authenticationTrustResolver;
                               }
                            
                               public void setCreateSessionAllowed(boolean createSessionAllowed) {
                                   this.createSessionAllowed = createSessionAllowed;
                               }
                            
                               public void setPortResolver(PortResolver portResolver) {
                                   this.portResolver = portResolver;
                               }
                            }
                            The above implementation of an ExceptionTranslationFilter should work. It unwinds the whole Exception stack to see if an AccessDeniedException or AuthenticationException is part of it. If so it handles it, else rethrow the exception.

                            Comment


                            • #44
                              It works great! Thanks.

                              One more question..i have to demo this to the client in a week so im hoping im near done... :-)

                              I have an insecure landing area that all users hit. called insecure-flow. i have set the default target url to be _flowId=secure-flow. Now if i have restricted that flow to ROLE_USER, and a particular user does not have ROLE_USER I get the Illegal state exception because they arent allowed into the flow. It seems that since it is an exception thrown within webflow that spring mvc has to handle it.

                              Acegi and the new exception translationfilter work great, but because the user has no access to the flow, but the flow was started swf throws an exception

                              i guess the question is... normally i am redirected to the standard access denied page when i try and access the even-more-secure-flow without acess. I think this is more of a swf problem than an acegi problem.

                              should i make the default target a sub-flow state of the insecure-flow?

                              can i access the flowExecutionKey from within acegi-security.xml?...

                              ie
                              Code:
                              	<bean id="authenticationProcessingFilter"
                              		class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
                              		<property name="authenticationManager"
                              			ref="authenticationManager" />
                              		<property name="authenticationFailureUrl"
                              			value="/rfsportal.rfs?_flowExecutionKey=flowScope.flowExecutionKey&_eventId=loginFail" />
                              		<property name="defaultTargetUrl" value="/rfsportal.rfs?_flowExecutionKey=flowScope.flowExecutionKey&_eventId=loginSuccess" />
                              		<property name="filterProcessesUrl"
                              			value="/j_acegi_security_check" />
                              		<property name="rememberMeServices" ref="rememberMeServices" />
                              	</bean>
                              should i remove the restriction to the flow and add restrictions to all events/states?

                              or do i leave the servlet exception handler in place and yell at the support guys when they muck up a user?
                              Last edited by trdyer; Nov 8th, 2007, 07:22 AM.

                              Comment


                              • #45
                                The solution is excellent. The problem was that the authenticationexception was being wrapped in another exception. Will This new filter be integrated into the new releases of ACEGI.

                                Thanks

                                Comment

                                Working...
                                X