Announcement Announcement Module
Collapse
No announcement yet.
Spring Security ACL tutorial Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Security ACL tutorial

    Hello,

    I would like to invite you to have a look at the "Spring Security ACL tutorial for PostgreSQL" that we published on our blog at http://www.denksoft.com (the link to it is on the first page).

    In this article we aim at explaining in detail the security configurations needed for ACL use, with a focus on the PostgreSQL database. In addition, we attach to the article a working application, called SpringStarter.

    I look forward to receiving your feedback and proposals for improvement.

    Regards,
    Ovidiu
    Last edited by Luke Taylor; Sep 5th, 2008, 07:03 AM. Reason: Added URL.

  • #2
    Looks really good. Thanks :-).

    Comment


    • #3
      A few minor things on reading through it.

      1. You shouldn't need to explicitly add the security interceptor to the bean (or declare it, in fact). With the <global-method-security /> element, your @Secured beans should automatically be intercepted. You can set the AccessDecisionManager directly on this element. With this approach, a default AfterInvocationManager is also maintained, so you can register the providers as described here:

      http://jira.springframework.org/browse/SEC-783

      The context sample should probably be updated to do this (I don't think it uses use Java 5 and annotations at the moment).

      2. Once 2.0.4 is released (soon), the recommended way of using role hierarchies will be via a voter:

      http://jira.springframework.org/browse/SEC-883

      3. "Hierarhical" is spelled wrongly

      Comment


      • #4
        hierarchical acls

        Luke - can you take a look at http://forum.springframework.org/sho...688#post210688

        I feel perhaps I am missing something. I know acl's can do hierarchical stuff on their own, but the hierarchies have to be in the database. RoleHierarchyVoter provides method (and ui?) access based on hierarchies but NOT for acls (eg AFTER_ACL_READ). I was hoping the RoleHierarchicalVoter changes would also have incorporated acl hierarchy roles. Conceptually this seems the way to go. No? But then we need access to change the sidRetrievalStrategy...

        Thanks,
        adam

        Comment


        • #5
          I need a sample

          Originally posted by Luke Taylor View Post
          A few minor things on reading through it.

          1. You shouldn't need to explicitly add the security interceptor to the bean (or declare it, in fact). With the <global-method-security /> element, your @Secured beans should automatically be intercepted. You can set the AccessDecisionManager directly on this element. With this approach, a default AfterInvocationManager is also maintained, so you can register the providers as described here:

          The context sample should probably be updated to do this (I don't think it uses use Java 5 and annotations at the moment).

          2. Once 2.0.4 is released (soon), the recommended way of using role hierarchies will be via a voter:

          3. "Hierarhical" is spelled wrongly
          Thanks, for this comments Luke. But can you give us a sample (how should I use <custom-after-invocation-provider> element)?

          Comment


          • #6
            When using a security:global-method-security bean, you need to remove your afterInvocationManager and simply insert the line security:custom-after-invocation-provider in each instance of afterAclRead and afterAclCollectionRead

            Code:
            	<!-- since we use global-security...we use the custom-after-invocation-provider to register the instances -->
            	<!--
            	<bean id="afterInvocationManager" class="org.springframework.security.afterinvocation.AfterInvocationProviderManager">
            		<property name="providers">
            			<list>
            				<ref local="afterAclRead"/>
            				<ref local="afterAclCollectionRead"/>
            			</list>
            		</property>
            	</bean>
            	-->
            
            	<!-- this picks up on AFTER_ACL_READ -->
            	<bean id="afterAclRead" class="org.springframework.security.afterinvocation.AclEntryAfterInvocationProvider">
            		<security:custom-after-invocation-provider/>
            		<constructor-arg>
            			<ref bean="aclService"/>
            		</constructor-arg>
            		<constructor-arg>
            			<list>
            				<ref local="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/>
            				<ref local="org.springframework.security.acls.domain.BasePermission.READ"/>
            			</list>
            		</constructor-arg>
            	</bean>
            
            	<!-- this picks up on AFTER_ACL_COLLECTION_READ -->
            	<bean id="afterAclCollectionRead" class="org.springframework.security.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider">
            		<security:custom-after-invocation-provider/>
            		<constructor-arg>
            			<ref bean="aclService"/>
            		</constructor-arg>
            		<constructor-arg>
            			<list>
            				<ref local="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/>
            				<ref local="org.springframework.security.acls.domain.BasePermission.READ"/>
            			</list>
            		</constructor-arg>
            	</bean>

            Comment


            • #7
              Thanks, for real quick reply! I'm going to try it right now)

              Comment


              • #8
                I'm looking through the Denksoft tutorial, and specifically at the objectManagerSecurity bean:

                HTML Code:
                    <bean id="objectManagerSecurity"
                          class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor" autowire="byType">        
                        <property name="accessDecisionManager" ref="businessAccessDecisionManager"/>
                        <property name="afterInvocationManager" ref="afterInvocationManager"/>        
                        <property name="objectDefinitionSource" ref="objectDefinitionSource"/>
                    </bean>
                So you're saying:

                1) pull out the afterInvocationManager and use <security:custom-after-invocation-provider/> instead (where the security namespace is defined as http://www.springframework.org/schema/security)

                2) pull out the accessDecisionManager and instead use the access-decision-manager-ref attribute on global-method-security like so:
                HTML Code:
                <global-method-security 
                    secured-annotations="enabled" 
                    jsr250-annotations="enabled"
                    access-decision-manager-ref="businessAccessDecisionManager"/>
                Now what about objectDefinitionSource? If I can chuck that then can I chuck the explicit objectManagerSecurity bean?

                Comment


                • #9
                  Alrighty then. objectDefinitionSource is taken care of in the <global-method-security/> tag attributes secured-annotation and/or jsr250-annotations.

                  Right?

                  So then in the example tutorial, this entire section:

                  HTML Code:
                      <bean id="objectDefinitionSource" class="org.springframework.security.annotation.SecuredMethodDefinitionSource" />
                  
                            class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor" autowire="byType">        
                          <property name="accessDecisionManager" ref="businessAccessDecisionManager"/>
                          <property name="afterInvocationManager" ref="afterInvocationManager"/>        
                          <property name="objectDefinitionSource" ref="objectDefinitionSource"/>
                      </bean>
                  can be chucked and replaced with:

                  HTML Code:
                      <global-method-security 
                      secured-annotations="enabled" 
                      jsr250-annotations="enabled"
                      access-decision-manager-ref="businessAccessDecisionManager"/>
                  plus using <security:custom-after-invocation-provider/> for the afterAclRead and afterAclCollectionRead beans as specified above.

                  Is this correct?

                  Comment


                  • #10
                    John - right on all counts AFAIK. You can chuck objectDefinitionSource and objectManagerSecurity.

                    Just for the record for others - these changes only affect the config files. Denksoft's example is still very much applicable and works as is, though I suspect most people are looking to extract a template which is up to date.

                    I haven't specifically tested the new setup with annotations but replacing objectDefinitionSource with secured-annotations="enabled" or jsr250-annotations="enabled" should work as you expect.

                    objectManagerSecurity is an alternative way (to global-method-security) of indicating what methods need security rights. Again, I haven't tested global-method-security with annotations - I populate it with <securityrotect-pointcut expression=".." access="..">

                    Quick note: If you're using the 'security' prefix for the schema, then don't forget it in <security:global-method-security ...>
                    Last edited by adam_jh; Jan 7th, 2009, 04:05 AM.

                    Comment


                    • #11
                      there's something I don't understand in the tutorial concerning roles

                      the example uses a RoleVoter
                      each principal (logged-in user) will have an authority (=role) which is ROLE_USER or ROLE_CLERK

                      why do you need to explicitly create an acl_entry for the SID "ROLE_CLERK"?

                      example:
                      Code:
                          @Secured({"ROLE_CLERK","AFTER_ACL_READ"})
                          public Clerk getClerk(long id);
                      in this case the RoleVoter will GRANT access, because the principal has ROLE_CLERK.

                      so there should be no need to exlicitly add a permission for each clerk:
                      Code:
                          public void setClerkPermissions(Clerk clerk) {
                              Sid sid = new PrincipalSid(clerk.getUser().getUsername());
                              aclSecurityUtil.addPermission(clerk, sid, BasePermission.ADMINISTRATION, Clerk.class);
                          }
                      I think this is redundant. What do you think?

                      BTW: thanks for the great tutorial

                      Comment


                      • #12
                        I think you are right, but where did you find this code? I looked throw Denksoft tutorial and didn't found anything similar =/

                        Comment


                        • #13
                          I looked directly at the sourcecode of the sample application.
                          The link to the sourcecode is under Reference [5] of the Tutorial
                          see classes:
                          • ClerkService: security annotations
                          • SecurityServiceImpl: setClerkPermissions() function
                          • PublicServiceImpl: will populate the database

                          Comment


                          • #14
                            look closer..
                            aclSecurityUtil.addPermission(clerk, sid, BasePermission.ADMINISTRATION, Clerk.class);
                            this string adds ADMINISTRATION permission to clerk, not ROLE_CLERK

                            Comment


                            • #15
                              BUG found:

                              PostgresqlJdbcMutableAclService.createOrRetrieveCl assPrimaryKey(Class, boolean)
                              PostgresqlJdbcMutableAclService.createOrRetrieveSi dPrimaryKey(Sid, boolean)

                              are not thread safe!


                              these methods can cause a SQL exception: constraint violation UNIQUE_UK_1
                              CREATE TABLE ACL_SID (
                              id BIGSERIAL NOT NULL PRIMARY KEY,
                              principal BOOLEAN NOT NULL,
                              sid VARCHAR(100) NOT NULL,
                              CONSTRAINT UNIQUE_UK_1 UNIQUE(sid,principal)
                              );
                              p.s. this code was copypasted from denksof blog

                              Comment

                              Working...
                              X