Announcement Announcement Module
Collapse
No announcement yet.
How do I move part of the set-up in the applicationContext.xml to Java code? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How do I move part of the set-up in the applicationContext.xml to Java code?

    I want to move the LdapAuthenticationProvider, FilterBasedLdapUserSearch and DefaultInitialDirContextFactory to Java code.

    Would I put that in a Java Bean or what is the correct way to do that?

    In other words, with my current applicationContext set-up, everything works great! How would I split the set-up between XML and Java code?

    Suggestions, examples or useful advice is greatly appreciated.

    Thank you.

    Full applicationContext.xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
            "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean class="org.acegisecurity.util.FilterChainProxy"
              id="filterChainProxy">
            <property name="filterInvocationDefinitionSource">
                <value>
                    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                    PATTERN_TYPE_APACHE_ANT
                    /**=httpSessionContextIntegrationFilter,rememberMeProcessingFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
                </value>
            </property>
        </bean>
        <bean class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"
                id="httpSessionContextIntegrationFilter"/>
    
        <bean id="rememberMeProcessingFilter"
              class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
            <property name="authenticationManager">
                <ref local="authenticationManager"/>
            </property>
            <property name="rememberMeServices">
                <ref local="rememberMeServices"/>
            </property>
        </bean>
    
        <bean id="rememberMeServices"
              class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
            <property name="userDetailsService">
                <ref local="ldapAuthProvider"/>
            </property>
            <property name="key">
                <value>springRocks</value>
            </property>
        </bean>
    
        <bean id="rememberMeAuthenticationProvider"
              class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
            <property name="key">
                <value>springRocks</value>
            </property>
        </bean>
    
        <bean id="logoutFilter"
              class="org.acegisecurity.ui.logout.LogoutFilter">
            <constructor-arg value="/index.jsp?event=0"/>
            <constructor-arg>
                <list>
                    <ref bean="rememberMeServices"/>
                    <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
                </list>
            </constructor-arg>
        </bean>
    
        <bean
                class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter"
                id="authenticationProcessingFilter">
            <property name="authenticationManager"
                      ref="authenticationManager"/>
            <property name="filterProcessesUrl">
                <value>/j_acegi_security_check</value>
            </property>
            <property name="authenticationFailureUrl">
                <value>/index.jsp?event=1</value>
            </property>
            <property name="defaultTargetUrl">
                <value>/eaigft/eaigft_add_option.jsf</value>
            </property>
        </bean>
    
        <bean
                class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"
                id="securityContextHolderAwareRequestFilter"/>
        <bean
                class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter"
                id="anonymousProcessingFilter">
            <property name="key" value="changeThis"/>
            <property name="userAttribute"
                      value="anonymousUser,ROLE_ANONYMOUS"/>
        </bean>
        <bean class="org.acegisecurity.ui.ExceptionTranslationFilter"
              id="exceptionTranslationFilter">
            <property name="authenticationEntryPoint">
                <bean
                        class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                    <property name="loginFormUrl" value="/index.jsp?event=0"/>
                    <property name="forceHttps" value="false"/>
                </bean>
            </property>
            <property name="accessDeniedHandler">
                <bean
                        class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
                    <property name="errorPage" value="/index.jsp?event=3"/>
                </bean>
            </property>
        </bean>
        <bean id="passwordEncoder"
              class="org.acegisecurity.providers.encoding.ShaPasswordEncoder"/>
        <bean class="org.springframework.jndi.JndiObjectFactoryBean"
              id="dataSource">
            <property name="resourceRef">
                <value>true</value>
            </property>
            <property name="jndiName">
                <value>jdbc/MyOracle</value>
            </property>
        </bean>
        <bean class="org.acegisecurity.vote.RoleVoter" id="roleVoter"/>
        <bean class="org.acegisecurity.vote.UnanimousBased"
              id="accessDecisionManager">
            <property name="allowIfAllAbstainDecisions">
                <value>false</value>
            </property>
            <property name="decisionVoters">
                <list>
                    <ref local="roleVoter"/>
                </list>
            </property>
        </bean>
        <bean
                class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"
                id="authenticationProcessingFilterEntryPoint">
            <property name="loginFormUrl">
                <value>/index.jsp</value>
            </property>
            <property name="forceHttps">
                <value>false</value>
            </property>
        </bean>
        <bean class="org.acegisecurity.vote.AffirmativeBased"
              id="httpRequestAccessDecisionManager">
            <property name="allowIfAllAbstainDecisions">
                <value>false</value>
            </property>
            <property name="decisionVoters">
                <list>
                    <ref bean="roleVoter"/>
                </list>
            </property>
        </bean>
        <bean
                class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"
                id="filterInvocationInterceptor">
            <property name="authenticationManager">
                <ref bean="authenticationManager"/>
            </property>
            <property name="accessDecisionManager">
                <ref local="httpRequestAccessDecisionManager"/>
            </property>
            <property name="objectDefinitionSource">
                <value>
                    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                    PATTERN_TYPE_APACHE_ANT
                    /index.jsp=ROLE_ANONYMOUS,ROLE_USERONE,ROLE_USERTWO
                    /common/**=ROLE_ANONYMOUS,ROLE_USERONE
                    /login/**=ROLE_ANONYMOUS,ROLE_USERONE,ROLE_USERTWO
                    /resources/**=ROLE_ANONYMOUS,ROLE_USERONE,ROLE_USERTWO
                    /browser/**=ROLE_USERONE
                    /theme/**=ROLE_ANONYMOUS,ROLE_USERONE,ROLE_USERTWO
                    /**=ROLE_ANONYMOUS,ROLE_USERONE,ROLE_USERTWO
                </value>
            </property>
        </bean>
        <bean class="org.acegisecurity.providers.ProviderManager" id="authenticationManager">
            <property name="providers">
                <list>
                    <ref local="ldapAuthProvider"/>
                    <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
                        <property name="key" value="changeThis"/>
                    </bean>
                    <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
                        <property name="key" value="changeThis"/>
                    </bean>
                </list>
            </property>
        </bean>
    
        <bean id="initialDirContextFactory"
              class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
            <constructor-arg value="ldap://url.company.com"/>
            <property name="managerDn">
                <value>CN=user,DC=company,DC=com</value>
            </property>
            <property name="managerPassword">
                <value>password</value>
            </property>
        </bean>
    
        <bean id="userSearch" class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
            <constructor-arg index="0">
                <value>OU=BusinessUnits,DC=company,DC=com</value>
            </constructor-arg>
            <constructor-arg index="1">
                <value>(&amp;(sAMAccountName={0}))</value>
            </constructor-arg>
            <constructor-arg index="2">
                <ref local="initialDirContextFactory"/>
            </constructor-arg>
            <property name="searchSubtree">
                <value>true</value>
            </property>
        </bean>
    
        <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
            <constructor-arg>
                <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
                    <constructor-arg>
                        <ref local="initialDirContextFactory"/>
                    </constructor-arg>
                    <property name="userSearch" ref="userSearch"/>
                </bean>
            </constructor-arg>
            <constructor-arg>
                <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
                    <constructor-arg>
                        <ref local="initialDirContextFactory"/>
                    </constructor-arg>
                    <constructor-arg>
                        <value>OU=DTN Groups,DC=company,DC=com</value>
                    </constructor-arg>
                    <property name="groupRoleAttribute">
                        <value>cn</value>
                    </property>
                </bean>
            </constructor-arg>
        </bean>
        <bean class="org.acegisecurity.event.authentication.LoggerListener"
              id="loggerListener"/>
    </beans>

  • #2
    Hi!

    What exactly do you want to achive?

    If you like to make the applicationContext unaware of LdapAuthenticationProvider, FilterBasedLdapUserSearch and DefaultInitialDirContextFactory it should be enough to wire your object graph in your JavaCode and removing them form the context.
    But for this you should have one bean defined that could be assigned to ProviderManager, otherwise your checks would not be resolved. That means that this bean has to implement the AuthenticationProvider interface.

    Or do you like to remove that assignment, too? So you have the applicationContext completly unaware of your Ldap checks? For these checks you could use a different filter than Acegis. But I would not do it, if I wanna use Acegi, because some parts of the security concern it defined here and other parts there. This would be bad.

    Or you like to achive a complete different thing. Please be more specific, maybe than I could help a little bit more.


    Best regards,

    Danny

    Comment


    • #3
      Agree with wizardOfOz (did I just type that :-)) if you can explain what you are trying to achieve might be able to help.

      Comment


      • #4
        Thank you for the responses.

        What I am trying to do is the following:
        1. User A logs in with a username and password.
        2. Username and password are authenticated against the LDAP tree.
        3. On a successful authentication, I'd like to obtain more properties about the user from the LDAP tree, such as their 'memberof' property.

        Or in general, be able to get any of the user's LDAP object properties upon a successful authentication - that is the bottom line.

        I see no means of accomplishing this with:

        Code:
        <bean id="initialDirContextFactory"
                  class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
                <constructor-arg value="ldap://url.company.com"/>
                <property name="managerDn">
                    <value>CN=user,DC=company,DC=com</value>
                </property>
                <property name="managerPassword">
                    <value>password</value>
                </property>
            </bean>
        
            <bean id="userSearch" class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
                <constructor-arg index="0">
                    <value>OU=BusinessUnits,DC=company,DC=com</value>
                </constructor-arg>
                <constructor-arg index="1">
                    <value>(&amp;(sAMAccountName={0}))</value>
                </constructor-arg>
                <constructor-arg index="2">
                    <ref local="initialDirContextFactory"/>
                </constructor-arg>
                <property name="searchSubtree">
                    <value>true</value>
                </property>
            </bean>
        
            <bean id="ldapAuthProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
                <constructor-arg>
                    <bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
                        <constructor-arg>
                            <ref local="initialDirContextFactory"/>
                        </constructor-arg>
                        <property name="userSearch" ref="userSearch"/>
                    </bean>
                </constructor-arg>
                <constructor-arg>
                    <bean class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
                        <constructor-arg>
                            <ref local="initialDirContextFactory"/>
                        </constructor-arg>
                        <constructor-arg>
                            <value>OU=DTN Groups,DC=company,DC=com</value>
                        </constructor-arg>
                        <property name="groupRoleAttribute">
                            <value>cn</value>
                        </property>
                    </bean>
                </constructor-arg>
            </bean>
        So my inital thought was take that set-up out of the applicationContext and use it in Java code to try to accomplish my goal.

        This is still a priority, so any suggestions are greatly appreciated.

        Thanks,

        Comment


        • #5
          Just having a quick look at the code the AbstractLdapAuthenticator which the BindAuthenticator extends has contains a String [] called userAttributes. These are the attributes to be retrieved, null means all attributes which is the default. Aren't you already getting all attibutes in the LdapUserDetails?

          Code:
          LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) template.retrieveEntry(userDn, getUserDetailsMapper(), getUserAttributes());

          Comment


          • #6
            karldmoore: Here is my disconnect and most likely my own inflicted pain.

            While I am using acegi-security, I am *not* using the Spring Framework. My project is a JSF project - so I followed the set-up and information at http://www.acegisecurity.org/articles.html - which works fine and my project is going quiet well.

            My disconnect is *where* would I place, for example, your code snippet?

            I assume in a Bean, since each JSF page is binded by a backing bean.

            As I work, I believe this may be working, but is it correct?

            Thanks,

            Comment


            • #7
              Originally posted by jtp51 View Post
              karldmoore: Here is my disconnect and most likely my own inflicted pain.

              While I am using acegi-security, I am *not* using the Spring Framework. My project is a JSF project - so I followed the set-up and information at http://www.acegisecurity.org/articles.html - which works fine and my project is going quiet well.

              My disconnect is *where* would I place, for example, your code snippet?

              I assume in a Bean, since each JSF page is binded by a backing bean.

              As I work, I believe this may be working, but is it correct?

              Thanks,
              What I was getting at is that I the code should already be there to do this from my basic scan of the code. If you download acegi source and look at the class I named it already retrieves attributes for the user account. If you want to name the attributes to retrieve you should just inject them into the BindAuthenticator.

              As for retrieving the details they are bound to thread local so something like the code below taken from the BasicProcessingFilter should get them.

              Code:
              Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
              LdapUserDetails details = (LdapUserDetails) existingAuth.getDetails();
              Obviously add a few more checks than this.
              Last edited by karldmoore; Oct 24th, 2006, 11:43 AM.

              Comment


              • #8
                Hi!

                I am not familar with Ldap, but I had to secure an existing webapp with existing user scheme, too. Furthermor the webapp uses JSF, too.

                Here is what I did:

                First of all I created a User that implements the UserDetails interface (I would like to extend the User from Acegi, but the User had to extend another class, so I stuck with implementing the interface).
                With this, my specific user could be handle throughout the Acegi FW. Afterward I enriched the new User class with all things I need throughout the app.
                But as karldmoore point out, there is already a LdapUserDetailsImpl that could be used for getting the attributes that are attached to the loggin user.

                Then I wrote a AuthenticationController for JSF. This is basicly a "simple" backing bean, with a login action. Here I tried to authenticate the User.

                Finally I coded a Service that implemented UserDetailService. In this I load everything that is needed throughout the system into an object of the new created user class.

                If you need your object, try the way karldmoore suggests:

                Code:
                Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
                <yourUserClass> details = (<yourUserClass>) existingAuth.getDetails();
                Your can easly access the SecurityContextHolder from everywhere in your code. If you like, I would send you my code, to see what I did.


                Best regards,

                Danny
                Last edited by wizardofOz; Oct 25th, 2006, 03:26 AM.

                Comment


                • #9
                  When I add the following to a constructor of my class:

                  Code:
                  Authentication userAuth = SecurityContextHolder.getContext().getAuthentication();
                          LdapUserDetails details = (LdapUserDetails) userAuth.getDetails();
                          this.setUserDetails(details.getDn());
                  I return the exception:

                  java.lang.ClassCastException: org.acegisecurity.ui.WebAuthenticationDetails

                  Where is a good example of how to use the SecurityContextHolder class? In other words, once a user has authenticated successfully, how can I get *any* of the user's details in Java code?

                  Thanks,
                  Last edited by jtp51; Oct 25th, 2006, 02:34 PM.

                  Comment


                  • #10
                    Hi!

                    After checking the JavaDocs and the guide again, I think there was a little mistake in karldmoore suggestion.

                    Try this instead:
                    Code:
                    Authentication userAuth = SecurityContextHolder.getContext().getAuthentication();
                            LdapUserDetails details = (LdapUserDetails) userAuth.getPrincipal();
                            this.setUserDetails(details.getDn());
                    This should do the job.


                    Best regards,

                    Danny

                    Comment


                    • #11
                      Yeah your right sorry about that. The principal has the UserDetails. That will teach me for trying to work at the same time as doing something else :-).

                      Comment


                      • #12
                        The DN is a String, so details.getDn() probably isn't what you want. Just the UserDetails object.

                        Comment


                        • #13
                          Everything is moving along smooth now, I appreciate everyone's help...

                          Staying on topic, I have the following:

                          Code:
                          Authentication userAuth = SecurityContextHolder.getContext().getAuthentication();
                                  LdapUserDetails details = (LdapUserDetails) userAuth.getPrincipal();
                                  this.setUserDetails(details.getAttributes().toString());
                          Which outputs the the details of my LDAP User's object - that is what I want.

                          Now, from that point - how do I get a specific LDAP attribute from this point?

                          For example, I just want to get the values for the memberOf attribute, such as:

                          memberOf: CN=Users,OU=exchange dist groups,OU=company Groups,DC=company,DC=com,
                          CN=VPN Users,OU=company Groups,DC=company,DC=com


                          Since I have a Principle object, the Authentication interface doesn't have a method to get a attribute by ID or name?

                          Thanks,

                          Comment


                          • #14
                            Hi!

                            The method getAttributes() on a UserDetails object delivers a collection, if I am not wrong.

                            See here:
                            http://www.acegisecurity.org/multipr...tailsImpl.html

                            and here:
                            http://java.sun.com/j2se/1.5.0/docs/...ttributes.html

                            From the Attributes object you should retrieve all values you need (with get(<attrID>)). As I told before, I am not familiar with Ldap, but this is how I see it from the docs and sources.


                            Best regards,

                            Danny

                            Comment


                            • #15
                              Thanks Danny, I missed that.

                              The following is what I needed:

                              Code:
                              Authentication userAuth = SecurityContextHolder.getContext().getAuthentication();
                                          LdapUserDetails details = (LdapUserDetails) userAuth.getPrincipal();
                                          Attributes attributes = details.getAttributes();
                                          Attribute attr = attributes.get("memberOf");
                                          String memberOf = String.valueOf(attr.get());

                              Comment

                              Working...
                              X