Announcement Announcement Module
Collapse
No announcement yet.
RoleHierarchy in GrantedAuthorities Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • RoleHierarchy in GrantedAuthorities

    I'm using Spring Security 3.0.4.RELEASE and I'm trying to figure out if RoleHierarchy can be used when simply looping through granted Authorities. Below is my config:

    Code:
    <beans:bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
            <beans:property name="roleHierarchy" ref="roleHierarchy" />
        </beans:bean>
    
        <!-- An expression handler used to secure methods.
             This overrides the DefaultMethodSecurityExpressionHandler to include roleHierarchy.
        -->
         <beans:bean id = "methodSecurityExpressionHandler" class = "org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
            <beans:property name = "roleHierarchy" ref ="roleHierarchy"/>
        </beans:bean> 
    
        <beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
            <beans:property name="hierarchy">
                <beans:value>
    			ROLE_ADMIN > ROLE_MANAGER
    			ROLE_MANAGER > ROLE_USER
                            ROLE_USER > ROLE_AUTHENTICATED
    			ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED
                </beans:value>
            </beans:property>
        </beans:bean>
        
        
        <global-method-security pre-post-annotations="enabled" secured-annotations="enabled">
            <security:expression-handler ref="methodSecurityExpressionHandler"/>
        </global-method-security>
        
        <!-- security:authorize tags using the url attribute will delegate to this accessDecisionManager -->
        <beans:bean id="webAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
            <beans:property name="decisionVoters">
                <beans:list>
                    <beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                        <beans:property name="expressionHandler" ref="webSecurityExpressionHandler" />
                    </beans:bean>
                </beans:list>
            </beans:property>
        </beans:bean>
    
        <http auto-config="true" use-expressions="true" access-decision-manager-ref="webAccessDecisionManager">
            <form-login login-page="/login" default-target-url="/"
                always-use-default-target="false"
                authentication-failure-url="/login?error=authorizationFailed" />
            <logout invalidate-session="true" logout-url="/logout"
                logout-success-url="/login?error=loggedOut" />
            <access-denied-handler error-page="/error?id=accessDenied" />
            <remember-me key="company-app-remember" />
            <!-- ... -->
        </http>
        <authentication-manager alias="authenticationManager">
            <ldap-authentication-provider
                user-search-filter="mail={0}" user-search-base="ou=people,o=company"
                user-context-mapper-ref="customUserDetailsContextMapper" group-search-base="ou=groups,o=company" />            
        </authentication-manager>
    So what I want to do is in my method check if the user is ROLE_MANAGER but if the user is ROLE_ADMIN then it should be included (as shown in the hierarchy). It doesn't seem that the granted authorities necessarily includes the other roles so I may have to check use the voter? I've also tried using @PreAuthorize("hasRole('ROLE_MANAGER'") on this method but it doesn't seem to be found. Is it required that @PreAuthorize work on only public methods? Thanks!

    Code:
        private void clientTaskDtoToClientTask(ClientTask clientTaskToUpdate, ClientTaskDto clientTaskDto) {
            for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) {
                if (authority.getAuthority().equals(Roles.ROLE_MANAGER)) {
                    log.info(String.format("Found role %s, setting assignment properties on client task.", Roles.ROLE_MANAGER));
                    //Update the clientTask fields
                    clientTaskToUpdate.setAssignedEmployee(clientTaskDto.getClientTask().getAssignedEmployee());
                    clientTaskToUpdate.setDueDate(clientTaskDto.getClientTask().getDueDate());
                }
            }
        }

  • #2
    Originally posted by dukethrash View Post
    So what I want to do is in my method check if the user is ROLE_MANAGER but if the user is ROLE_ADMIN then it should be included (as shown in the hierarchy). It doesn't seem that the granted authorities necessarily includes the other roles so I may have to check use the voter?
    RoleHeiarchy does not add the roles to the users' GrantedAuthority. See the logic inside the RoleHierarchyVoter to see how to use the RoleHiearchy. An example of using it is:

    Code:
    Collection<GrantedAuthority> authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
    Originally posted by dukethrash View Post
    I've also tried using @PreAuthorize("hasRole('ROLE_MANAGER'") on this method but it doesn't seem to be found. Is it required that @PreAuthorize work on only public methods? Thanks!
    You are using proxy based aop, so private methods are not considered. I suggest you read Spring's AOP chapter for details on how it works.

    Comment


    • #3
      That worked! Thank you. I ended up doing the following
      Code:
          
      @Autowired
      private RoleHierarchy roleHierarchy;
      
      // ...
      
      private void clientTaskDtoToClientTask(ClientTask clientTaskToUpdate, ClientTaskDto clientTaskDto) {
              Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
              Collection<GrantedAuthority> authorities = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
      
              for (GrantedAuthority authority : authorities) {
                  if (authority.getAuthority().equals(Roles.ROLE_MANAGER)) {
                      log.info(String.format("Found role %s, setting assignment properties on client task", authority.getAuthority()));
      
                      //Update the clientTask fields
                      clientTaskToUpdate.setAssignedEmployee(clientTaskDto.getClientTask().getAssignedEmployee());
                      clientTaskToUpdate.setDueDate(clientTaskDto.getClientTask().getDueDate());
                  }
              }
          }
      It seems like the RoleHierarchy implementation is not so much integrated into GrantedAuthorities and documentation is somewhat weak (even for upcoming Spring Security 3.1). It would be nice to be able to set the RoleHierarchy in the Authentication the same way you can for AccessDecisionManagers.

      Comment


      • #4
        Originally posted by dukethrash View Post
        It would be nice to be able to set the RoleHierarchy in the Authentication the same way you can for AccessDecisionManagers.
        One reason to keep it out of the Authentication is to keep the values stored in session to a minimum. You can always write your own Authentication implementation that does this.

        Comment

        Working...
        X