Announcement Announcement Module
Collapse
No announcement yet.
Multiple Authentication Entry Points Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multiple Authentication Entry Points

    Hi,

    I'm replacing my own Security mechanisms with Acegi in an App where currently I have seperate login forms for admin and users.

    Can someone suggest the best approach to doing this in Acegi? I understand I could make things work with a single entrypoint for all domains but I'd like to be able to stick with my current setup.

    Cheers
    Darragh

  • #2
    Are you planning on using net.sf.acegisecurity.webapp.AuthenticationProcessi ngFilter (most people do)?

    If so, probably the simplest is to configure two instances of that filter in web.xml, with different AuthenticationProcessingFilter.filterProcessesUrl and AuthenticationProcessingFilter.authenticationFailu reUrl.

    Of course, it would be cleaner to have one login form (but I'm sure you've got your reasons)...

    Comment


    • #3
      I have encountered the same problem: the homepage needed a login form, and when the user wants to access thoese authorized pages, another login form is needed.

      After I configure two filters in web.xml and two securityEnforcementFilters and two authenticationProcessingFilterEntryPoints in applicationContext.xml,
      it seems that only one filter take effect.

      Can someone sugguest a approach to do this in Acegi?

      Comment


      • #4
        When you say there are two login forms, I assume the user can login to either one of them and avoid needing to login again or separately through the second login form?

        I'm not sure why this isn't working. Although if you just want a convenience login box on your home page, why not get it to post to /j_acegi_security_check, being the same post target as your normal login form? You shouldn't need separate login processing filters.

        If this doesn't help, please post a debug-level log from AuthenticationProcessingFilter,

        Comment


        • #5
          Let me explain why I must do in such a way.

          Our webapp has a home page, and authorized users have their personal home page. The login form exists in two pages: one for home page, another one for a separated login page.

          The original page flow is user can login from both the above pages, and will be redirected to their personal home page. But now the page flow will be changed in such a way: if user login from home page, then he will stay in the home page, but if he login from the seperated login page, then he will be redirected to his personal main page. So, as you can see, one entry point is not enough.

          The configuration for applicationContext.xml is like such:
          Code:
          <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
          		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
          		<property name="authenticationFailureUrl"><value>/loginError.jsp</value></property>
          		<property name="defaultTargetUrl"><value>/mainMenu.html</value></property>
          		<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
          	</bean>
          
          	<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
          		<property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
          		<property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint"/></property>
          	</bean>
          
          	<bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
          		<property name="loginFormUrl"><value>/login.jsp</value></property>
          		<property name="forceHttps"><value>false</value></property>
          	</bean>
          	
          	<bean id="authenticationProcessingFilter2" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
          		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
          		<property name="authenticationFailureUrl"><value>/loginMainError.jsp</value></property>
          		<property name="defaultTargetUrl"><value>/userWelcome.jsp</value></property>
          		<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
          	</bean>
          	<bean id="authenticationProcessingFilterEntryPoint2" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
          		<property name="loginFormUrl"><value>/loginMain.jsp</value></property>
          		<property name="forceHttps"><value>false</value></property>
          	</bean>
          	<bean id="securityEnforcementFilter2" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
          		<property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
          		<property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint2"/></property>
          	</bean>
          But when I login from either login form, I will be redirected to the same page: /userWelcome.jsp.

          Comment


          • #6
            Both filters are defined to process /j_acegi_security_check. You need one to process say /j_acegi_security_check_home_page and one /j_acegi_security_check_personal_page to achieve your goal.

            Comment


            • #7
              Originally posted by Ben Alex
              Both filters are defined to process /j_acegi_security_check. You need one to process say /j_acegi_security_check_home_page and one /j_acegi_security_check_personal_page to achieve your goal.
              /j_acegi_security_check_home_page and /j_acegi_security_check_personal_page ? Can I define the authorize url in any name?

              Thank you for your reply. I will test this.

              Comment


              • #8
                I have tested this configuration as you recommended. I changed the /j_acegi_security_check on the home page to /j_acegi_security_check_home, and the other one is /j_acegi_seurity_check. But when I login from the separated login form(not the form in the home page), I got a error that /j_acegi_seurity_check cann't find. And when I enter an authorized page without login, the login form will be the form in the home page.

                I was wondering whether the configuration is correct or not. Can you give me some more suggestions?

                Comment


                • #9
                  You said /j_acegi_seurity_check, which might be a typo or might be the problem. Please post the application context, as well as a debug-level log, and I'll be happy to take a look.

                  Comment


                  • #10
                    Sorry for my typing error. It is "/j_acegi_security_check".

                    applicationContext.xml :
                    Code:
                    <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
                    		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
                    		<property name="authenticationFailureUrl"><value>/loginError.jsp</value></property>
                    		<property name="defaultTargetUrl"><value>/mainMenu.html</value></property>
                    		<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
                    	</bean>
                    
                    	<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
                    		<property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
                    		<property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint"/></property>
                    	</bean>
                    
                    	<bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                    		<property name="loginFormUrl"><value>/login.jsp</value></property>
                    		<property name="forceHttps"><value>false</value></property>
                    	</bean>
                    	
                    	<bean id="authenticationProcessingFilter2" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
                    		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
                    		<property name="authenticationFailureUrl"><value>/loginMainError.jsp</value></property>
                    		<property name="defaultTargetUrl"><value>/userWelcome.jsp</value></property>
                    		<property name="filterProcessesUrl"><value>/j_acegi_security_check_home</value></property>
                    	</bean>
                    	<bean id="authenticationProcessingFilterEntryPoint2" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                    		<property name="loginFormUrl"><value>/loginMain.jsp</value></property>
                    		<property name="forceHttps"><value>false</value></property>
                    	</bean>
                    	<bean id="securityEnforcementFilter2" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
                    		<property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
                    		<property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint2"/></property>
                    	</bean>
                    web.xml:
                    Code:
                    <filter>
                            <filter-name>Acegi Authentication Processing Filter</filter-name>
                            <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
                            <init-param>
                                <param-name>targetClass</param-name>
                                <param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value>
                            </init-param>
                        </filter>
                        <filter>
                            <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
                            <filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilter</filter-class>
                        </filter>
                        <filter>
                            <filter-name>Acegi HTTP Request Security Filter</filter-name>
                            <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
                            <init-param>
                                <param-name>targetClass</param-name>
                                <param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
                            </init-param>
                    </filter>
                        
                    <filter>
                            <filter-name>Acegi Authentication Processing Filter2</filter-name>
                            <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
                            <init-param>
                                <param-name>targetClass</param-name>
                                <param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value>
                            </init-param>
                    </filter>
                        
                    <filter>
                            <filter-name>Acegi HTTP Request Security Filter2</filter-name>
                            <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
                            <init-param>
                                <param-name>targetClass</param-name>
                                <param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
                            </init-param>
                    </filter>
                    
                    <!-- filter mappings -->
                    <filter-mapping>
                          <filter-name>Acegi Authentication Processing Filter</filter-name>
                          <url-pattern>/*</url-pattern>
                    </filter-mapping>
                    	
                    <filter-mapping>
                          <filter-name>Acegi Authentication Processing Filter2</filter-name>
                          <url-pattern>/*</url-pattern>
                    </filter-mapping>
                    
                    <filter-mapping>
                          <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
                          <url-pattern>/*</url-pattern>
                        </filter-mapping>
                        
                    <filter-mapping>
                          <filter-name>Acegi HTTP Request Security Filter</filter-name>
                          <url-pattern>/*</url-pattern>
                    </filter-mapping>
                        
                    <filter-mapping>
                          <filter-name>Acegi HTTP Request Security Filter2</filter-name>
                          <url-pattern>/*</url-pattern>
                    </filter-mapping>
                    [/code]

                    Comment


                    • #11
                      You don't need two SecurityEnforcementFilters and you don't need two AuthenticationFilterEntryPoints.

                      The AuthenticationFilterEntryPoint is used by SecurityEnforcementFilter whenever an AuthenticationException is detected. In other words, when SecurityEnforcementFilter decides the user needs to logon, it launches AuthenticationFilterEntryPoint. You can only have one such filter per webapp. If you really need more customised handling, such as the intended login form is based on the request that was made which failed, you'll need to write your own AuthenticationEntryPoint.

                      It should also be noted the AuthenticationProcessingFilter.defaultTargetUrl is only called when the login was not as a result of the AuthenticationFilterEntryPoint. If it was the result of the AuthenticationFilterEntryPoint, the SecurityEnforcementFilter will have told the AuthenticationProcessingFilter (via the HttpSession) the URL that should be displayed post-authentication. That URL should be the secured page the user requested but was denied. The defaultTargetUrl only applies if the user logged in of their own accord - not as a result of the application prompting them to. If you want to always ignore the AuthenticationFilterEntryPoint target URL, your best course of action is to write a custom AuthenticationEntryPoint which changes the HttpSession parameter.

                      Hope this explains a bit more clearly what is going on.

                      Comment


                      • #12
                        Thank you for your explain about the filters.

                        I have realized that the filters in web.xml are redundant after I posted the last post. Then I removed them. But the result still was not what I want.

                        I have ever thought to write a MutliAuthenticationEntryPoint class to accomplish this task, but I didn't understant fully the internal relationships.

                        Now I used a trick to fulfill this task: write a jsp file for home page login form and a servlet, and in the servlet, get the authenticationManager to authenticate and put the authentication object into session, and this does works well.

                        Maybe I will rethink to implement my AuthenticationEntryPoint later.

                        Anyway, many thanks for your help.

                        Comment


                        • #13
                          Originally posted by simontang_tang
                          Now I used a trick to fulfill this task: write a jsp file for home page login form and a servlet, and in the servlet, get the authenticationManager to authenticate and put the authentication object into session, and this does works well.
                          Just double-check it really does work as you intend. A lot of people write directly to the HttpSession and then get surprised when strange things happen. Your AbstractIntegrationFilter does this:

                          1. Retrieve from the well-known location (typically HttpSession) the Authentication
                          2. Populate ContextHolder with Authentication
                          3. Proceed with request (ie your web controller/servlet etc runs now)
                          4. Retrieve from the ContextHolder the Authentication
                          5. Write the retrieved Authentication back to the well-known location

                          So your HttpSession may get overwritten with null if you just set it via your servlet.

                          I'd encourage instead to customise an AuthenticationEntryPoint. It's really easy to do. This is the entire interface:

                          Code:
                              public void commence&#40;ServletRequest request, ServletResponse response&#41;
                                  throws IOException, ServletException;
                          So your implementation just looks at the request URL, and decides the correct URL to put into HttpSession parameter defined by AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL _KEY (which would have earlier been set by the SecurityEnforcementFilter).

                          If a login form is presented because of a user wish to login - as opposed to your SecurityEnforcementFilter detecting a problem and delegating to AuthenticationEntryPoint - the defaultTargetUrl defined against the responding AuthenticationProcessingFilter will be used.

                          Comment


                          • #14
                            Yesterday my trick has encountered a problem: the login process on the home page is correct; but when I entered into user's personal home page, it's correct in the first time, and after I logged out from personal home page, then redirect to home page, the process was also correct. But when I logged in again and entered into personal home page, the login form page showed while personal information showed on the page is correct. Could you give me some hints about this problem?

                            Today I implemented a AuthenticationEntryPoint as you stated, the code like such:
                            Code:
                            public class EdusuppAuthenticationEntryPoint extends
                                    AuthenticationProcessingFilterEntryPoint &#123;
                                private static final Log logger = LogFactory.getLog&#40;EdusuppAuthenticationEntryPoint.class&#41;;
                                
                                private PortResolver portResolver = new PortResolverImpl&#40;&#41;;
                                
                                public void setPortResolver&#40;PortResolver portResolver&#41; &#123;
                                    this.portResolver = portResolver;
                                &#125;
                            
                                public PortResolver getPortResolver&#40;&#41; &#123;
                                    return portResolver;
                                &#125;
                                
                                /* &#40;non-Javadoc&#41;
                                 * @see net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint#commence&#40;javax.servlet.ServletRequest, javax.servlet.ServletResponse&#41;
                                 */
                                public void commence&#40;ServletRequest request, ServletResponse response&#41;
                                        throws IOException, ServletException &#123;
                                    HttpServletRequest req = &#40;HttpServletRequest&#41; request;
                                    String scheme = request.getScheme&#40;&#41;;
                                    String serverName = request.getServerName&#40;&#41;;
                                    int serverPort = portResolver.getServerPort&#40;request&#41;;
                                    String contextPath = req.getContextPath&#40;&#41;;
                            
                                    boolean includePort = true;
                            
                                    if &#40;"http".equals&#40;scheme.toLowerCase&#40;&#41;&#41; && &#40;serverPort == 80&#41;&#41; &#123;
                                        includePort = false;
                                    &#125;
                            
                                    String redirectUrl = scheme + "&#58;//" + serverName
                                        + &#40;&#40;includePort&#41; ? &#40;"&#58;" + serverPort&#41; &#58; ""&#41; + contextPath;
                            
                                    if&#40;req.getRequestURL&#40;&#41;.indexOf&#40;"userWelcome"&#41; != -1&#41; &#123;
                                        redirectUrl += "/loginMain.jsp";
                                        
                                        req.getSession&#40;&#41;.setAttribute&#40;AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, redirectUrl&#41;;
                                        
                                        if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                            logger.debug&#40;"Redirecting to&#58; " + redirectUrl&#41;;
                                        &#125;
                            
                                        &#40;&#40;HttpServletResponse&#41; response&#41;.sendRedirect&#40;&#40;&#40;HttpServletResponse&#41; response&#41;
                                            .encodeRedirectURL&#40;redirectUrl&#41;&#41;;
                                    &#125; else &#123;
                                         super.commence&#40;request, response&#41;;
                                    &#125;
                                &#125;
                            &#125;
                            loginMain.jsp is the login form page will be show in the home page using IFrame, and the iframe will linked userWelcome.jsp, this page required the user to be authorized. The problem is when I access the home page, the login form showed but after authorized, the login form still shows. When I access the personal home page, it shows the user's personal information.

                            Would you like to check the problem? Many thanks.

                            Comment


                            • #15
                              Let's try and simplify things a bit.

                              I presume you're still using this config:

                              Code:
                              <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
                                    <property name="authenticationManager"><ref bean="authenticationManager"/></property>
                                    <property name="authenticationFailureUrl"><value>/loginError.jsp</value></property>
                                    <property name="defaultTargetUrl"><value>/mainMenu.html</value></property>
                                    <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
                              </bean> 
                              
                              <bean id="authenticationProcessingFilter2" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
                                    <property name="authenticationManager"><ref bean="authenticationManager"/></property>
                                    <property name="authenticationFailureUrl"><value>/loginMainError.jsp</value></property>
                                    <property name="defaultTargetUrl"><value>/userWelcome.jsp</value></property>
                                    <property name="filterProcessesUrl"><value>/j_acegi_security_check_home</value></property>
                              </bean>
                              I also presume your /loginMain.jsp login form redirects to /j_acegi_security_check. I presume your home page login form POSTs to /j_acegi_security_check_home.

                              Next up disable any IFRAMEs and start your web container from scratch. If you visit /loginMain.jsp, login as a user, does it post to /j_acegi_security_check and then redirect to /mainMenu.html?

                              Next shutdown your web container and start it again without any IFRAMEs. If you visit your home page login form, does it POST to /j_acegi_security_check_home and then redirect to /userWelcome.jsp?

                              This basic initial behaviour does not in any way involve an AuthenticationEntryPoint. It's solely as a result of user login requests.

                              Ensure your "logout" operation is actually a HttpSession invalidation, rather than any overwriting an HttpSession attribute or ContextHolder value.

                              Once you've proven your basic configuration works, next try accessing a secure page when you're not logged in. Look at the debug logs and ensure the entry point redirects to the correct login page. Then check that login page, subsequent to successful login, redirects to the AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL _KEY (which your entry point will have overwritten if required).

                              Comment

                              Working...
                              X