配置Spring Security 4,以便可以在XML中使用“<sec:authorize url =”...“>”标记

时间:2015-08-12 16:46:05

标签: spring spring-security

我有一个工作的java 8 Web应用程序,它使用Spring框架4.2和Spring Security 4.0.2通过Jasig CAS(中央身份验证服务)处理身份验证,使用LDAP对抗我们的Active Directory服务器。

目前,我使用像这样的“授权”JSP标记库(http://docs.spring.io/spring-security/site/docs/4.0.2.RELEASE/reference/htmlsingle/#taglibs-authorize)......

<sec:authorize var="allowRename" access="hasRole('ROLE_TEST_RENAME')" />
<input id="allowRename" type="hidden" value="${allowRename}" />

此方法的缺点是直接在视图中引用Active Directory安全组。我宁愿不这样做。相反,我希望改变它,使它看起来像这样......

<sec:authorize var="allowRename" url="/rename.json" />
<input id="allowRename" type="hidden" value="${allowRename}" />

这样,我可以在一个地方配置访问 - 在spring安全配置中。

根据文档,要在authorize标记上使用url属性,我的应用程序上下文中必须有一个WebInvocationPrivilegeEvaluator实例。当我使用安全命名空间时,它不是xml配置文件中的基本命名空间 - 所以我理解我必须手动声明DefaultWebInvocationPrivilegeEvaluator类的实例。该类的构造函数采用AbstractSecurityInterceptor类型的单个参数,但就我所见,我没有任何引用。

这是我的(自然编辑)配置 - 有没有人知道如何修改它以便我可以使用对FilterSecurityInterceptor的单个构造函数参数声明来声明DefaultWebInvocationPrivilegeEvaluator bean?

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <security:http entry-point-ref="casEntryPoint">
        <security:intercept-url pattern="/rename.json" method="POST" 
            access="hasRole('ROLE_TEST_RENAME')" />
        <security:intercept-url pattern="/delete.json" method="POST" 
            access="hasRole('ROLE_TEST_DELETE')" />
        <security:intercept-url pattern="/restore.json" method="POST" 
            access="hasRole('ROLE_TEST_DELETE')" />
        <security:intercept-url pattern="/**" 
            access="hasRole('ROLE_TEST_USERS')" />

        <security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER" />
        <security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER" />
        <security:custom-filter ref="casFilter" position="CAS_FILTER" />

        <security:logout logout-success-url="${cas.server.rootUrl}/logout" 
            invalidate-session="true" />
    </security:http>

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="casAuthenticationProvider" />
    </security:authentication-manager>

    <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
        <constructor-arg value="ldap://ldap.test.com:389/dc=test,dc=com"/>
        <property name="url" value="ldap://ldap.test.com:389/" />
        <property name="base" value="dc=test,dc=com" />
        <property name="pooled" value="true" />
        <property name="userDn" value="${ad.userDn}" />
        <property name="password" value="${ad.password}" />
    </bean>

    <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
        <constructor-arg name="searchBase" value="ou=User Accounts,ou=TEST" />
        <constructor-arg name="searchFilter" value="(sAMAccountName={0})" />
        <constructor-arg ref="contextSource" />
    </bean>

    <bean id="authoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
        <constructor-arg ref="contextSource" />
        <constructor-arg value="ou=Group Accounts,ou=TEST" />
        <property name="groupRoleAttribute" value="cn" />
        <property name="searchSubtree" value="true" />
        <property name="rolePrefix" value="ROLE_" />
        <property name="defaultRole" value="ROLE_USER" />
        <property name="convertToUpperCase" value="true" />
    </bean>

    <bean id="userDetailsMapper" class="com.test.security.auth.ActiveDirectoryUserDetailsMapper" />

    <bean id="ldapUserDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
        <constructor-arg ref="userSearch" />
        <constructor-arg ref="authoritiesPopulator" />
        <property name="userDetailsMapper" ref="userDetailsMapper" />
    </bean>

    <!-- handles a Single Logout Request from the CAS Server -->
    <bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter">
        <property name="casServerUrlPrefix" value="${cas.server.secureUrl}" />
    </bean>

    <!-- redirects to the CAS Server to signal Single Logout should be performed -->
    <bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg value="${cas.client.contextRootUrl}/logout" />
        <constructor-arg>
            <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
        </constructor-arg>
        <property name="filterProcessesUrl" value="/logout/cas" />
    </bean>

    <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
        <property name="service" value="${cas.client.contextRootUrl}/login/cas" />
        <property name="authenticateAllArtifacts" value="true" />
        <property name="sendRenew" value="false" />
    </bean>

    <bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
        <property name="loginUrl" value="${cas.server.rootUrl}/login" />
        <property name="serviceProperties" ref="serviceProperties" />
    </bean>

    <bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="serviceProperties" ref="serviceProperties" />
    </bean>

    <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
        <property name="authenticationUserDetailsService">
            <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                <constructor-arg ref="ldapUserDetailsService" />
            </bean>
        </property>
        <property name="serviceProperties" ref="serviceProperties" />
        <property name="ticketValidator">
            <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                <constructor-arg index="0" value="${cas.server.rootUrl}" />
            </bean>
        </property>
        <property name="key" value="test-application" />
    </bean>

</beans>

1 个答案:

答案 0 :(得分:1)

只是为了澄清每当我使用我的初始帖子中描述的authorize标签时,它总是解析为true。问题是,在某些情况下,根据我登录的人,它应该已经解决为false

我刚刚弄明白为什么,现在它的工作原理应该如此。

基本上,问题出在这里......

<sec:authorize var="allowRename" url="/rename.json" />

我看一下上面的配置,你会看到“/rename.json”网址对它有一个method="POST"限制。为了使标记正常工作,我必须对其进行修改,以便它还指定方法...

<sec:authorize var="allowRename" url="/rename.json" method="POST" />

谢谢大家的帮助。