将应用程序从spring security 3迁移到4,面临RoleVoter类的问题

时间:2015-06-03 12:33:00

标签: java spring spring-mvc spring-security

我们正在将我们的应用程序从Spring 3.0.1升级到Spring 4.1.6。我们还将Spring Security Module升级到4.0.1

我们面临的问题是访问链接。

小背景:

每个链接都标记为某个ROLE,以访问用户需要具有该ROLE的链接

<security:http  auto-config="false" access-decision-manager-ref="urlAccessDecisionManager" entry-point-ref="authenticationEntryPoint" use-expressions="true">
    <security:access-denied-handler error-page="/admin/error.html" /> 
    <security:csrf disabled="true"/>
    <security:session-management invalid-session-url="/admin/sign-in.html" >
       <!--<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />  -->
    </security:session-management>
    <security:form-login login-page="/admin/sign-in.html" authentication-success-handler-ref="loginSuccessHandler" default-target-url="/admin/index.html"
                         username-parameter="j_username"
                         password-parameter="j_password"
                         login-processing-url="/j_spring_security_check"
                         always-use-default-target="false"
                         authentication-failure-url="/admin/sign-in.html?error=1" />

    <security:logout logout-url="/admin/logout.html" invalidate-session="true" logout-success-url="/admin/sign-in.html"/>   
    <security:intercept-url pattern="/admin/index.html*" access="ROLE_ADMIN_OVERALL_DASHBOARD" />
    <security:intercept-url pattern="/admin/accounts/index.html*" access="ROLE_ADMIN_ACCOUNT_LISTING" />
     ......
     ......
     ......

  </security:http>

为了做出访问决定,我们有 urlAccessDecisionManager ,以及三名选民,如下所示:

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
<bean id="urlAccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    <constructor-arg>
        <list>
            <ref bean="roleVoter" />
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
            <ref bean="urlCustomVoter"/>
        </list>
    </constructor-arg>
    </bean>

问题在于,即使角色以&#39; ROLE _&#39;(在阅读不同的博客和问题后发现这一点)开始,角色也无法正常工作。所以为了找到问题,我调试了spring安全源,发现RoleVoter的supports()方法返回false。所以我进一步研究了这个方法:

public boolean supports(ConfigAttribute attribute) {
        if ((attribute.getAttribute() != null)
                && attribute.getAttribute().startsWith(getRolePrefix())) {
            return true;
        }
        else {
            return false;
        }
    }

事实证明 attribute.getAttribute()返回NULL,因为该属性是 WebExpressionConfigAttribute 类型的对象,默认情况下为 getAttributed()返回NULL 方法。

同时我调试了使用Spring Security 3.0.1的旧代码,发现在旧代码中属性对象的类型为 SecurityConfig

有人可以指出我们所做的配置错误,即使用户已经标记了所有ROLES,用户也无法访问链接。

1 个答案:

答案 0 :(得分:2)

Spring Security 4.x Migration Guide引用sample project on Github,显示XML配置所需的更改,以便在URL上强制执行特定角色。

根据样本,行:

<security:intercept-url pattern="/admin/index.html*"
                        access="ROLE_ADMIN_OVERALL_DASHBOARD" />

需要更改为:

<security:intercept-url pattern="/admin/index.html*" 
                        access="hasRole('ROLE_ADMIN_OVERALL_DASHBOARD')" />

(角色名称需要包含在对hasRole()的调用中。

使用Spring Security 4.x时,也可以从角色名称中省略ROLE_前缀,因为Spring JIRA 2758的修复确保前缀自动应用于没有该前缀的角色名称。< / p>