Announcement Announcement Module
Collapse
No announcement yet.
Multiple 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 Entry Points

    Hi, I have a web application that I am trying to migrate to using Spring Security. I really like what I have seen so far. I was able to easily connect to my existing user service and object by implementing the UserDetailsService and UserDetails interface.

    The issue I am running into is that I need to have multiple login forms.

    What I am trying to do in more detail is have two (or more) protected resource areas with something like:

    <form-login login-page="/area1Login.jsp" authentication-failure-url="/area1Login.jsp?login_error=1" default-target-url="/area1/index.jsp" />

    <intercept-url pattern="/area1/**" access="IS_AUTHENTICATED_REMEMBERED" />


    and then:

    <form-login login-page="/area2Login.jsp" authentication-failure-url="/area2Login.jsp?login_error=1" default-target-url="/area2/index.jsp" />

    <intercept-url pattern="/area2/**" access="IS_AUTHENTICATED_REMEMBERED" />


    Is this possible? Is there any documentation on how I would go about doing this?

    Thanks.

  • #2
    Well then you need to set up two different security configurations, each covering a different set of URLs.

    Are you sure though that groups is not the thing you need? I don't know your use-case but it sounds little redundant to facilitate the exact same feature with two or more implementations. If you are however convinced that you need this than you can do it like above.

    Comment


    • #3
      You can't have multiple <form-login> elements in the same configuration so I would recommend replacing this with a customized AuthenticationProcessingFilter and AuthenticationProcessingFilterEntry point instead. The entry point could dynamically determine the login page as you see fit.

      Comment


      • #4
        Sorry for my ignorance. I am new to Spring Security. I am not sure what you mean by "groups" I searched through the reference document and did not find anything related to groups other than the LDAP authentication.

        Maybe I was not very clear in my first post. What am trying to accomplish is to have the login form on multiple pages of the site and have Spring Security know which page is doing the post so it can present invalid credentials, account expired, account locked, credentials expired messages back to the correct page. The site only has one level of authorization so once a user has successfully authenticated from any login form they can access any of the secured resources.

        Comment


        • #5
          Okay I will investigate a customized AuthenticationProcessingFilter and AuthenticationProcessingFilterEntry point. Does that mean I need to go to the full "Acegi" type configuration and not use the <http> security namespace config?

          Also, does this JIRA SEC-486 issue (can't post the full url) affect how I need to setup my entry point configuration?

          Comment


          • #6
            Originally posted by sdavis View Post
            Maybe I was not very clear in my first post. What am trying to accomplish is to have the login form on multiple pages of the site and have Spring Security know which page is doing the post so it can present invalid credentials, account expired, account locked, credentials expired messages back to the correct page. The site only has one level of authorization so once a user has successfully authenticated from any login form they can access any of the secured resources.
            If that's the case, then you should only need an AuthenticationProcessingFilter and set the parameter "spring-security-redirect" in your login submission to the page you want to return to (check out the TargetUrlResolverImpl class). Alternatively, try making use of the Referer header to decide where you should return to.

            Comment


            • #7
              Luke, thanks for your advice. I figured it out from what you said. It probably took me longer than it should but I learned a lot by tracing through the code.

              For anyone else searching through the forums and wanting to do something similar, I am showing what my config turned out to be.

              This assumes the following directory structure

              /area1
              /area1/secure
              /area2
              /area2/secure

              and the login forms are in /area1/index.jsp and /area2/index.jsp and that anything under the secure folders is a protected resource.

              <?xml version="1.0" encoding="UTF-8"?>

              <beans:beans xmlns=" THE SYSTEM WON'T LET ME POST URLS SO ADD NORMAL applicationContext-security.xml STUFF HERE">

              <authentication-manager alias='authenticationManagerAlias'/>

              <beans:bean id="area2AuthenticationProcessingFilter" class="org.springframework.security.ui.webapp.Auth enticationProcessingFilter">
              <beans: property name="filterProcessesUrl" value="/area2/j_spring_security_check_area2" />
              <beans: property name="defaultTargetUrl" value="/area2/secure/index.jsp"/>
              <beans: property name="authenticationFailureUrl" value="/area2/index.jsp?login_error=1"/>
              <beans: property name="authenticationManager" ref="authenticationManagerAlias"/>
              <custom-filter after="AUTHENTICATION_PROCESSING_FILTER" />
              </beans:bean>

              <http>
              <form-login login-processing-url="/area1/j_spring_security_check_area1" login-page="/area1/index.jsp" authentication-failure-url="/area1/index.jsp?login_error=1" default-target-url="/area1/secure/index.jsp" />

              <intercept-url pattern="/area1/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
              <intercept-url pattern="/area2/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
              <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />

              <anonymous />
              <logout />
              <remember-me key="myUniqueKey" user-service-ref="myUserDetailsService" />
              </http>

              <authentication-provider user-service-ref="myUserDetailsService" />

              </beans:beans>


              The defaultTargetUrl can be overwritten in the login form using

              <input type="hidden" name="spring-security-redirect"
              value="/area2/secure/someOtherSecure.jsp" />


              I Hope this helps somebody out.

              Comment


              • #8
                Hi
                i need to implement, multiple entry points (2 specific.)
                have you found a better solution?

                Comment


                • #9
                  you have helped a lot!!! Thanks for your effort!
                  /b

                  Comment


                  • #10
                    A better solution might perhaps be redirecting to either section after login? I don't think you are having 2 seperate login procedures here. What I would do would be to secure each resource with different roles, then implement a custom TargetUrlResolver like so.


                    security-context.xml

                    Code:
                    ...
                    
                    <security:http   access-decision-manager-ref="accessDecisionManager" auto-config="false"  entry-point-ref="formLoginAuthenticationEntryPoint">
                            <security:intercept-url  pattern="/section1/**" access="roles.first" />
                            <security:intercept-url  pattern="/section2/**" access="roles.second" />
                            
                            
                    <security:logout logout-success-url="/index.htm" logout-url="/secure_logout"/>
                      
                    </security:http>
                        
                    <bean id="customTargetUrlResolver" class="mypackage.security.CustomTargetUrlResolver">
                             <property name="sectionTwoDefaultUrl" value="/section2/index.htm"/>
                             <property name="sectionOneDefaultUrl" value="/section1/index.htm"/>
                    </bean>
                        
                    <bean id="formLoginFilter"  class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter" >
                    
                     <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
                    
                          <property name="authenticationFailureUrl" value="/login.htm?error=1" />
                          <property name="authenticationManager" ref="authenticationManager"/> 
                          <property name="filterProcessesUrl" value="/secure_login"/>
                          <property name="allowSessionCreation" value="true" />
                          <property name="targetUrlResolver" ref="customTargetUrlResolver"/>
                    </bean>
                        
                    ...
                    So we basically just define the targetUrlResolver, which will be something like this:

                    Code:
                    public class CustomTargetUrlResolver implements TargetUrlResolver {
                    
                        private String sectionOneDefaultUrl;
                        private String sectionTwoDefaultUrl;
                    
                        public String getSectionTwoDefaultUrl() {
                            return sectionTwoDefaultUrl;
                        }
                    
                        public void setSectionTwoDefaultUrl(String sectionTwoDefaultUrl) {
                            this.sectionTwoDefaultUrl = sectionTwoDefaultUrl;
                        }
                    
                        public String getSectionOneDefaultUrl() {
                            return sectionTwoDefaultUrl;
                        }
                    
                        public void setSectionOneDefaultUrl(String sectionOneDefaultUrl) {
                            this.sectionOneDefaultUrl = sectionOneDefaultUrl;
                        }
                    
                    
                        @Override
                        public String determineTargetUrl(SavedRequest savedRequest, HttpServletRequest currentRequest,
                                Authentication auth) {
                    
                            //Get user's roles
                                  for (GrantedAuthority authority : auth.getAuthorities()) {
                    
                                    if (authority.toString().equals("roles.second")) {
                                       
                                        return getSectionTwoDefaultUrl();
                    
                                    } else if (authority.toString().equals("roles.first")) {
                    
                                        return getSectionOneDefaultUrl();
                                    }
                    
                    
                                }
                      
                    
                      //User has none of the roles but is authenticated, redirect below.
                            return "/authenticated/index.html";
                        }
                    
                     
                    }
                    Of course you can go a lot crazier and flexible with it. You can set a list of paired "Role to redirect" default URLs and set them in your xml config, and so on.

                    Hope this helps.

                    Comment


                    • #11
                      Multiple Entry Points

                      Hi sdavis

                      I've the exact requirements as yours. Thank you very much for your code snippet!

                      But how is the second login page "/area2/index.jsp" specified through your code ?

                      Thank you very much in advance!

                      Comment


                      • #12
                        Originally posted by Luke Taylor View Post
                        You can't have multiple <form-login> elements in the same configuration so I would recommend replacing this with a customized AuthenticationProcessingFilter and AuthenticationProcessingFilterEntry point instead. The entry point could dynamically determine the login page as you see fit.
                        Hello Sir,

                        I wud just lyk to ask some assistance, as i cant get my config to work. How would I configure my application to have multiple AuthenticationProcessingFilter and AuthenticationProcessingFilterEntry point. I tried looking for some docs for spring security, but i cnt find some (i cant locate the previous docs, it always gives me a 404 not found error).
                        I have 2 login pages: /jsp/Guest.do and /jsp/subaccount/SubaccountIndex.do. Both login forms allow a certain roles to be logged in. . And the resources are also grouped, according to the roles. I have created custom authentication manager for this. my first login page works just fine (/jsp/Guest.do), it only allows a certain user to be logged in. but my second login page (/jsp/subaccount/SubaccountIndex.do) does not work, since everytym i submit the form, it always gives me a 404 Not Found error. Can you please pinpoint where my mistakes are? Thank you very much for the assistance.

                        Here's my config for security.xml:

                        PHP Code:
                              
                            
                        <bean id="springSecurityFilterChain" class="org.springframework.security.util.FilterChainProxy">
                                <
                        security:filter-chain-map path-type="ant">
                                    <
                        security:filter-chain filters="none" pattern="/jsp/subaccount/SubaccountIndex.do"/>
                                    <
                        security:filter-chain filters="none" pattern="/jsp/subaccount/GetCaptchaImage.do"/>
                                    <
                        security:filter-chain filters="none" pattern="/jsp/subaccount/j_spring_security_check"/>
                                    <
                        security:filter-chain filters="none" pattern="/jsp/subaccount/j_spring_security_logout"/>
                                    <
                        security:filter-chain pattern="/jsp/subaccount/**" 
                                        
                        filters="httpSessionContextIntegrationFilter, subaccountLogoutFilter,
                                        subaccountAuthenticationProcessingFilter, securityContextHolderAwareRequestFilter,
                                        subaccountExceptionTranslationFilter, sessionFixationProtectionFilter,
                                        subaccountFilterSecurityInterceptor" 
                        />
                                    <
                        security:filter-chain pattern="/jsp/**" 
                                        
                        filters="httpSessionContextIntegrationFilter, logoutFilter, 
                                        customerAuthenticationProcessingFilter, securityContextHolderAwareRequestFilter, 
                                        customerExceptionTranslationFilter, sessionFixationProtectionFilter, 
                                        customerFilterSecurityInterceptor"
                        />
                                </
                        security:filter-chain-map>
                            </
                        bean>

                            <
                        bean id="httpSessionContextIntegrationFilter" class="org.springframework.security.context.HttpSessionContextIntegrationFilter">
                                <
                        property name="allowSessionCreation" value="true" />
                                <
                        property name="forceEagerSessionCreation" value="false" />
                                <
                        property name="contextClass" value="org.springframework.security.context.SecurityContextImpl" />
                            </
                        bean>
                            
                            <
                        bean id="customerAuthenticationProcessingFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
                                <
                        property name="invalidateSessionOnSuccessfulAuthentication" value="true" />
                                <
                        property name="authenticationManager" ref="customerAuthenticationManager" />
                                <
                        property name="authenticationFailureUrl" value="/jsp/Guest.do?error=2" />
                                <
                        property name="defaultTargetUrl" value="/jsp/customer/Home.do" />
                                <
                        property name="filterProcessesUrl" value="/jsp/j_spring_security_check" />
                            </
                        bean>
                            
                            <
                        bean id="subaccountAuthenticationProcessingFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
                                <
                        property name="invalidateSessionOnSuccessfulAuthentication" value="true" />
                                <
                        property name="authenticationManager" ref="subaccountAuthenticationManager" />
                                <
                        property name="authenticationFailureUrl" value="/jsp/subaccount/SubAccountIndex.do?error=2" />
                                <
                        property name="defaultTargetUrl" value="/jsp/subaccount/SubAccountHome.do" />
                                <
                        property name="filterProcessesUrl" value="/jsp/subaccount/j_spring_security_check" />
                            </
                        bean>
                            
                            <
                        bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter" />
                            
                            <
                        bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
                                <
                        constructor-arg value="/jsp/Guest.do" />
                                <
                        constructor-arg>
                                    <list>
                                        <
                        bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" />
                                    </list>
                                </
                        constructor-arg>
                                <
                        property name="filterProcessesUrl" value="/jsp/j_spring_security_logout" />
                            </
                        bean>
                            
                            <
                        bean id="subaccountLogoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
                                <
                        constructor-arg value="/jsp/subaccount/SubAccountIndex.do" />
                                <
                        constructor-arg>
                                    <list>
                                        <
                        bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" />
                                    </list>
                                </
                        constructor-arg>
                                <
                        property name="filterProcessesUrl" value="/jsp/subaccount/j_spring_security_logout" />
                            </
                        bean>
                            
                            <
                        bean id="customerExceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter">
                                <
                        property name="authenticationEntryPoint">
                                    <
                        bean class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                                        <
                        property name="loginFormUrl" value="/jsp/Guest.do" />
                                        <
                        property name="forceHttps" value="false" />
                                    </
                        bean>
                                </
                        property>
                                <
                        property name="accessDeniedHandler" ref="accessDeniedHandler" />
                            </
                        bean>
                            
                            <
                        bean id="subaccountExceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter">
                                <
                        property name="authenticationEntryPoint">
                                    <
                        bean class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                                        <
                        property name="loginFormUrl" value="/jsp/subaccount/SubAccountIndex.do"/>
                                        <
                        property name="forceHttps" value="false" />
                                    </
                        bean>
                                </
                        property>
                                <
                        property name="accessDeniedHandler" ref="accessDeniedHandler" />
                            </
                        bean>
                            
                            <
                        bean id="accessDeniedHandler" class="org.springframework.security.ui.AccessDeniedHandlerImpl">
                                <
                        property name="errorPage" value="/403.jsp"/>
                            </
                        bean>
                            
                            <
                        bean id="sessionFixationProtectionFilter" class="org.springframework.security.ui.SessionFixationProtectionFilter" />
                            
                            <
                        bean id="customerFilterSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
                                <
                        property name="accessDecisionManager" ref="httpRequestAccessDecisionManager" />
                                <
                        property name="authenticationManager" ref="customerAuthenticationManager" />
                                <
                        property name="objectDefinitionSource">
                                    <
                        security:filter-invocation-definition-source>
                                        <
                        security:intercept-url pattern="/jsp/*.jsp" access="_NO_ACCESS_" />
                                        <
                        security:intercept-url pattern="/jsp/customer/*.jsp" access="_NO_ACCESS_"/>
                                        <
                        security:intercept-url pattern="/jsp/customer/**" access="CUSTOMERS" />
                                        <
                        security:intercept-url pattern="/jsp/partner/*.jsp" access="_NO_ACCESS_"/>
                                        <
                        security:intercept-url pattern="/jsp/partner/**" access="PARTNERS" />
                                    </
                        security:filter-invocation-definition-source>
                                </
                        property>
                            </
                        bean>
                            
                            <
                        bean id="subaccountFilterSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
                                <
                        property name="accessDecisionManager" ref="httpRequestAccessDecisionManager" />
                                <
                        property name="authenticationManager" ref="subaccountAuthenticationManager" />
                                <
                        property name="objectDefinitionSource">
                                    <
                        security:filter-invocation-definition-source>
                                        <
                        security:intercept-url pattern="/jsp/subaccount/*.jsp" access="_NO_ACCESS_"/>
                                        <
                        security:intercept-url pattern="/jsp/subaccount/*.do" access="SUBACCOUNT"/>
                                    </
                        security:filter-invocation-definition-source>
                                </
                        property>
                            </
                        bean>

                            <
                        bean id="httpRequestAccessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
                                <
                        property name="allowIfAllAbstainDecisions" value="false" />
                                <
                        property name="decisionVoters">
                                    <list>
                                        <
                        bean class="org.springframework.security.vote.AuthenticatedVoter" />
                                        <
                        bean class="org.springframework.security.vote.RoleVoter">
                                            <
                        property name="rolePrefix" value="" />
                                        </
                        bean>
                                    </list>
                                </
                        property>
                            </
                        bean>
                            
                            <
                        bean id="customerAuthenticationManager" class="crown.security.CustomerAuthenticationManager">
                                <
                        property name="customersService" ref="myService"/>
                                <
                        property name="passwordEncoder" ref="passwordEncoder" />
                            </
                        bean>
                            
                            <
                        bean id="subaccountAuthenticationManager" class="crown.security.SubaccountAuthenticationManager">
                                <
                        property name="customersService" ref="myService" />
                                <
                        property name="passwordEncoder" ref="passwordEncoder" />
                            </
                        bean>
                            
                            <
                        bean id="anonymousAuthentciationProvider" class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider">
                                <
                        property name="key" value="doesNotMatter" />
                            </
                        bean>
                            
                            <
                        bean id="rememberMeAuthenticationProvider" class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider">
                                <
                        property name="key" value="SpringSecured" />
                            </
                        bean>
                            
                            <
                        bean id="authenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
                                <
                        property name="hideUserNotFoundExceptions" value="false" />
                                <
                        property name="userDetailsService" ref="customersDao" />
                                <
                        property name="passwordEncoder" ref="passwordEncoder" />
                            </
                        bean>
                        </
                        beans
                        and in my web.xml, i have these:
                        PHP Code:
                            <filter>
                                <
                        filter-name>springSecurityFilterChain</filter-name>
                                <
                        filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
                            </
                        filter
                            <
                        filter-mapping>
                                <
                        filter-name>springSecurityFilterChain</filter-name>
                                <
                        url-pattern>/*</url-pattern>
                            </filter-mapping> 
                        Last edited by marcKun; Aug 31st, 2009, 02:31 PM.

                        Comment


                        • #13
                          Originally posted by sdavis View Post
                          <authentication-manager alias='authenticationManagerAlias'/>

                          <beans:bean id="area2AuthenticationProcessingFilter" class="org.springframework.security.ui.webapp.Auth enticationProcessingFilter">
                          <beans: property name="filterProcessesUrl" value="/area2/j_spring_security_check_area2" />
                          <beans: property name="defaultTargetUrl" value="/area2/secure/index.jsp"/>
                          <beans: property name="authenticationFailureUrl" value="/area2/index.jsp?login_error=1"/>
                          <beans: property name="authenticationManager" ref="authenticationManagerAlias"/>
                          <custom-filter after="AUTHENTICATION_PROCESSING_FILTER" />
                          </beans:bean>

                          <http>
                          [INDENT] <form-login login-processing-url="/area1/j_spring_security_check_area1" login-page="/area1/index.jsp" authentication-failure-url="/area1/index.jsp?login_error=1" default-target-url="/area1/secure/index.jsp" />

                          <intercept-url pattern="/area1/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
                          <intercept-url pattern="/area2/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
                          <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />

                          <anonymous />
                          <logout />
                          <remember-me key="myUniqueKey" user-service-ref="myUserDetailsService" />
                          </http>
                          For the sake of symmetry you can also declare two AuthenticationProcessingFilter beans (one for each area) and then neuter the one in the declarative http section like this:

                          <security:form-login login-processing-url="/NONE"/>

                          If you don't have a form-login at all it doesn't work. The only tricky part was that you can't have two filters at the same position so after="xxx" only works once. I resorted to using after and before for the two filter positions... but if I had three I guess I'd have to find a better solution.

                          This all seems way too hard... I think we should fix this... the http should allow multiple form-login elements.


                          Pat

                          Comment


                          • #14
                            multiple http form

                            Does anybody know if this feature is on the roadmap ?
                            I would also need multiple authentification inside my app.

                            Comment

                            Working...
                            X