2012-10-30 95 views
1

我無法獲得sec:authorize hasRole()以使用角色層次結構。如果我有一個ROLE_BOSS角色的用戶,它是ROLE_WORKER的父級角色,那麼由於某種原因它是錯誤的。然而,在我的服務類@PreAuthorize(「hasRole('ROLE_WORKER')」)確實有效。我認爲他們都使用了相同的評估器,爲什麼taglib不工作?謝謝您的幫助。Spring Security taglib sec:授權與角色層次結構不起作用

JSP:

<sec:authorize access="hasRole('ROLE_BOSS')"> 
    <p>This shows up.</p> 
</sec:authorize> 
<sec:authorize access="hasRole('ROLE_WORKER')"> 
    <p>This does not show up, but should.</p> 
</sec:authorize> 

-config.xml安全:

<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> 
    <property name="permissionEvaluator" ref="permissionEvaluator"/> 
    <property name="roleHierarchy" ref="roleHierarchy"/> 
</bean> 

<sec:global-method-security pre-post-annotations="enabled"> 
    <sec:expression-handler ref="expressionHandler"/> 
</sec:global-method-security> 

<bean id="permissionEvaluator" class="com.myapp.security.MyPermissionEvaluator"> 
    <constructor-arg index="0"> 
    <map key-type="java.lang.String" value-type="com.myapp.security.Permission"> 
     <entry key="contractReadAccess" value-ref="contractReadPermission"/> 
     <entry key="contractWriteAccess" value-ref="contractWritePermission"/> 
    </map> 
    </constructor-arg> 
</bean> 

<bean id="contractReadPermission" class="com.myapp.security.ContractReadPermission"/> 
<bean id="contractWritePermission" class="com.myapp.security.ContractWritePermission"/> 

<sec:http use-expressions="true" access-decision-manager-ref="accessDecisionManager"> 
    <sec:intercept-url pattern="/worker/**" access="isAuthenticated()" requires-channel="https"/> 
    <sec:intercept-url pattern="/boss/**" access="hasRole('ROLE_BOSS')" requires-channel="https"/> 

    <sec:form-login login-page="/login" authentication-failure-url="/login?login_error=1" authentication-success-handler-ref="successHandler"/> 
    <sec:logout logout-url="/logout" logout-success-url="/login" invalidate-session="true"/> 
<sec:remember-me/> 
</sec:http> 

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> 
    <constructor-arg> 
    <list> 
     <ref bean="roleVoter" /> 
     <bean class="org.springframework.security.web.access.expression.WebExpressionVoter"> 
     <property name="expressionHandler"> 
      <bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"> 
      <property name="roleHierarchy" ref="roleHierarchy"/> 
      </bean> 
     </property> 
     </bean> 
     <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/> 
    </list> 
    </constructor-arg> 
</bean> 

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter"> 
    <constructor-arg ref="roleHierarchy" /> 
</bean> 

<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"> 
    <property name="hierarchy"> 
    <value> 
     ROLE_BOSS > ROLE_WORKER 
    </value> 
    </property> 
</bean> 

<sec:authentication-manager alias="authenticationManager"> 
    <sec:authentication-provider user-service-ref="myUserDetailsService"/> 
</sec:authentication-manager> 

回答

1

很奇怪,我不認爲這是正確的,但它似乎工作。我開始通過Spring源代碼進行挖掘,我認爲通過將DefaultWebSecurityExpressionHandler從accessDecisionManager中取出並將其置於所有安全配置的頂層,可以使其工作。因此,在我的-config.xml頂部我有這樣的:

<bean id="webExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"> 
    <property name="permissionEvaluator" ref="permissionEvaluator"/> 
    <property name="roleHierarchy" ref="roleHierarchy"/> 
</bean> 

現在我的AccessDecisionManager是:

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> 
    <constructor-arg> 
    <list> 
     <ref bean="roleVoter" /> 
     <bean class="org.springframework.security.web.access.expression.WebExpressionVoter"> 
     <property name="expressionHandler" ref="webExpressionHandler"/> 
     </bean> 
     <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/> 
    </list> 
    </constructor-arg> 
</bean> 
0

您是否嘗試過?

<%@ taglib prefix='sec' uri='http://www.springframework.org/security/tags' %> 

<sec:authorize ifAnyGranted='ROLE_BOSS,ROLE_WORKER'> 
    <h1>ROLE_BOSS and ROLE_WORKER can see this</h1><br/> 
</sec:authorize> 

<sec:authorize access="hasAnyRole('ROLE_BOSS','ROLE_WORKER')"> 
    <h1>ROLE_BOSS and ROLE_WORKER can see this</h1><br/> 
</sec:authorize> 
+1

當然,將工作,但具有角色層次背後的想法是,我沒有每一個定義我的所有角色時間。我只需要定義層次結構中最低的角色,並且每個人都從中繼承。 – Jeremy

0

對於像我這樣的Java配置工作。這是一個非常簡單的解決方案在這裏只需添加以下代碼在類擴展WebSecurityConfigurerAdapter

@Bean 
    public RoleHierarchyVoter roleVoter() { 
     return new RoleHierarchyVoter(roleHierarchy()); 
    } 

    @Bean 
    public RoleHierarchy roleHierarchy() { 
     RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
     roleHierarchy.setHierarchy("ROLE_BOSS > ROLE_WORKER"); 
     return roleHierarchy; 
    } 

    private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { 
     DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); 
     defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy()); 
     return defaultWebSecurityExpressionHandler; 
    } 

    @Override 
    public void init(WebSecurity web) throws Exception { 
     web.expressionHandler(webExpressionHandler()); 
     super.init(web); 
    } 
相關問題