Spring安全角色层次结构问题 [英] Spring Security Role Hierarchy issues

查看:122
本文介绍了Spring安全角色层次结构问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Waffle NTML进行身份验证时在Spring Security中启用角色层次结构投票,但是存在一些未知的问题,因为继承的角色不会像预期的那样显示为主体上的授权机构,这会阻止在拦截URL和使用授权jsp taglibs.

I am trying to enable role hierarchy voting in Spring Security when authenticating using Waffle NTML but having some unknown issues in that the inherited roles do not appear as authorities on the principal as expected preventing hasRole expressions in both the intercept urls and using the authorize jsp taglibs.

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

I have been integrating waffle based on the following guide: https://github.com/dblock/waffle/blob/master/Docs/spring/SpringSecuritySingleSignOnFilter.md

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

This works within the application as expected on its own using the standard RoleVoter but the problem starts when I try to customise it to use the RoleHierarchyVoter which I have also tested on its own (using an LDAP Authentication Provider) and the role hierarchies work exactly as expected.

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

The config for the combined Waffle and RoleHierarchyVoter approach is as follows:

华夫饼专用配置

<!-- 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安全性源的几个小时后发现的http名称空间配置遗漏.

Managed to fix my issues which was down to an omission in my http namespace configuration which I found from hours of debugging the spring security source.

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

The issue was how the DefaultWebSecurityExpressionHandler was created. In the snipped above it had created it as inner bean inside the bean definition of the accessDecisionManager:

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

使用此角色heirachies来确定处理定义为拦截URL的规则时是否应授予访问权限:

With this the role heirachies are used to determine whether access should be granted when processing rules defined as intercept urls such as:

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

但是,如果要使用以下JSP Authorize标签库(在freemarker中)检查授权,则该角色将不起作用,因为不会考虑到角色Heirachies:

But if you want to check authorisation using the JSP Authorize taglib as below (this is in freemarker) it will not work as the roleHeirachies do not get taken into account:

<@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 默认豆(不使用RoleHierarchy),除非定义了安全性http名称空间表达式处理程序.

This is because the DefaultWebSecurityExpressionHandler created as an inner bean is only used within the access decision manager but for taglib expressions a NEW default bean will be created (which doesn't use the RoleHierarchy) unless an security http namespace expression-handler is defined.

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

So, to resolve my issues I created the bean DefaultWebSecurityExpressionHandler and referenced it within my WebExpressionVoter bean definition and also used it as the expression handler as follows:

<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标签库的表达式.

Making these changes ensures the roleHeirarchies are taken into account for both Web Security Expressions defined as intercept URLs via the http namespace and also expressions using the JSP Authorize taglib.

这篇关于Spring安全角色层次结构问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆