【问题标题】:Spring Security Role Hierarchy issuesSpring Security 角色层次结构问题
【发布时间】:2012-12-01 09:26:43
【问题描述】:

我试图在使用 Waffle NTML 进行身份验证时启用 Spring Security 中的角色层次投票,但有一些未知问题,即继承的角色不会像预期的那样显示为主体上的权限,从而阻止拦截 url 中的 hasRole 表达式和使用授权jsp taglibs。

我一直在根据以下指南集成华夫饼:https://github.com/dblock/waffle/blob/master/Docs/spring/SpringSecuritySingleSignOnFilter.md

这使用标准 RoleVoter 在应用程序中按预期工作,但是当我尝试自定义它以使用我也测试过的 RoleHierarchyVoter 时问题就开始了独立(使用 LDAP 身份验证提供程序)并且角色层次结构完全按预期工作。

Waffle 和 RoleHierarchyVoter 组合方法的配置如下:

华夫饼特定配置

<!-- windows authentication provider -->
<bean id="waffleWindowsAuthProvider" class="waffle.windows.auth.impl.WindowsAuthProviderImpl" />

<!-- collection of security filters -->
<bean id="negotiateSecurityFilterProvider" class="waffle.servlet.spi.NegotiateSecurityFilterProvider">
    <constructor-arg ref="waffleWindowsAuthProvider" />
</bean>

<bean id="basicSecurityFilterProvider" class="waffle.servlet.spi.BasicSecurityFilterProvider">
    <constructor-arg ref="waffleWindowsAuthProvider" />
</bean>

<bean id="waffleSecurityFilterProviderCollection" class="waffle.servlet.spi.SecurityFilterProviderCollection">
    <constructor-arg>
        <list>
            <ref bean="negotiateSecurityFilterProvider" />              
            <ref bean="basicSecurityFilterProvider" />              
        </list>
    </constructor-arg>
</bean>

<bean id="negotiateSecurityFilterEntryPoint" class="waffle.spring.NegotiateSecurityFilterEntryPoint">
    <property name="Provider" ref="waffleSecurityFilterProviderCollection" />
</bean>

<!-- spring security filter -->
<bean id="waffleNegotiateSecurityFilter" class="waffle.spring.NegotiateSecurityFilter">
    <property name="Provider" ref="waffleSecurityFilterProviderCollection" />
    <property name="AllowGuestLogin" value="false" />
    <property name="PrincipalFormat" value="fqn" />
    <property name="RoleFormat" value="fqn" />
    <property name="GrantedAuthorityFactory" ref="simpleGrantedAuthorityFactory" />
    <!-- set the default granted authority to null as we don't need to assign a default role of ROLE_USER -->
    <property name="defaultGrantedAuthority"><null/></property>

</bean>

<!-- custom granted authority factory so the roles created are based on the name rather than the fqn-->
<bean id="simpleGrantedAuthorityFactory" class="xx.yy.zz.SimpleGrantedAuthorityFactory">
    <constructor-arg name="prefix" value="ROLE_"/>
    <constructor-arg name="convertToUpperCase" value="true"/>
</bean>

熟悉的 Spring Security 配置

<!-- declare the entry point ref as the waffle defined entry point -->
<sec:http use-expressions="true"
          disable-url-rewriting="true"
          access-decision-manager-ref="accessDecisionManager"
          entry-point-ref="negotiateSecurityFilterEntryPoint" >

    <sec:intercept-url pattern="/**" access="isAuthenticated()" requires-channel="any"/>

    .
    . access denied handlers, concurrency control, port mappings etc
    .

    <sec:custom-filter ref="waffleNegotiateSecurityFilter" position="BASIC_AUTH_FILTER" />

</sec:http>

<!-- spring authentication provider -->
<sec:authentication-manager alias="authenticationProvider" />


<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="decisionVoters">
        <list>
            <ref bean="roleHierarchyVoter" />
            <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>
        </list>
    </property>
</bean>

<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_TEST_1 > ROLE_TEST_2
            ROLE_TEST_2 > ROLE_TEST_3
            ROLE_TEST_3 > ROLE_TEST_4
        </value>
    </property>
</bean>

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

【问题讨论】:

    标签: spring spring-security roles waffle


    【解决方案1】:

    设法解决了我的问题,这是我在调试 spring 安全源数小时后发现的 http 命名空间配置中的一个遗漏。

    问题在于 DefaultWebSecurityExpressionHandler 是如何创建的。在上面的片段中,它在 accessDecisionManager 的 bean 定义中将其创建为内部 bean:

    <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>
    

    这样,角色层次结构用于确定在处理定义为拦截 url 的规则时是否应授予访问权限,例如:

    <sec:intercept-url pattern="/**" access="isAuthenticated()" requires-channel="any"/>
    

    但是,如果您想使用如下的 JSP Authorize taglib 检查授权(这是在 freemarker 中),它将无法正常工作,因为没有考虑到 roleHierachies:

    <@security.authorize access="hasRole('ROLE_TEST_1)">
        <p>You have role 1</p>
    </@security.authorize>
    
    <@security.authorize access="hasRole('ROLE_TEST_4')">
        <p>You have role 4</p>
    </@security.authorize>
    

    这是因为作为内部 bean 创建的 DefaultWebSecurityExpressionHandler 仅在访问决策管理器中使用,但对于 taglib 表达式,将创建 NEW 默认 bean(不使用 RoleHierarchy),除非定义了安全 http 命名空间表达式处理程序。

    因此,为了解决我的问题,我创建了 bean DefaultWebSecurityExpressionHandler 并在我的 WebExpressionVoter bean 定义中引用它,并将其用作表达式处理程序,如下所示:

    <sec:http ... >
    
        .
        . access denied handlers, concurrency control, port mappings etc
        .
    
        <sec:expression-handler ref="defaultWebSecurityExpressionHandler" />
    
    </sec:http>
    
    <bean id="defaultWebSecurityExpressionHandler"
          class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
          <property name="roleHierarchy" ref="roleHierarchy"/>
    </bean>
    
    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <ref bean="roleHierarchyVoter" />
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                    <property name="expressionHandler" ref="defaultWebSecurityExpressionHandler"/>
                </bean>
            </list>
        </property>
    </bean>
    

    进行这些更改可确保将 roleHeirarchies 考虑到通过 http 命名空间定义为拦截 URL 的 Web 安全表达式以及使用 JSP Authorize taglib 的表达式。

    【讨论】:

      猜你喜欢
      • 2016-01-03
      • 2019-06-21
      • 2011-11-21
      • 2011-11-03
      • 2013-10-31
      • 1970-01-01
      • 2016-09-06
      • 2014-11-13
      • 2011-01-31
      相关资源
      最近更新 更多