使用 CAS 进行身份验证和 LDAP 进行授权的 Spring 项目

Posted

技术标签:

【中文标题】使用 CAS 进行身份验证和 LDAP 进行授权的 Spring 项目【英文标题】:Spring project using CAS for Authentication and LDAP for Authorities 【发布时间】:2012-06-26 23:55:20 【问题描述】:

我有一个 Spring 3 项目,它使用 LDAP 进行身份验证和授权。我们知道将项目更改为使用 CAS 进行身份验证,但仍然像使用 LDAP 进行授权一样工作。有人可以看看这个 XML 文件并告诉我如何让 LDAP 授权恢复和工作

  <?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
    xmlns="http://www.springframework.org/schema/security" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <http entry-point-ref="casEntryPoint" use-expressions="true">
        <intercept-url pattern="/" access="permitAll" />

        <intercept-url pattern="/index.jsp" access="permitAll" />
        <intercept-url pattern="/cas-logout.jsp" access="permitAll" />
        <intercept-url pattern="/casfailed.jsp" access="permitAll" />

        <intercept-url pattern="/secure/**" access="hasRole('ROLE_USER')" />
        <intercept-url pattern="/requests/**" access="hasRole('ROLE_MEMBER_INQUIRY')" />

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


        <logout logout-success-url="/cas-logout.jsp" />
    </http>

    <authentication-manager alias="authManager">
        <authentication-provider ref="casAuthProvider" />
    </authentication-manager>


     <user-service id="userService">
        <user name="rod" password="rod" authorities="ROLE_SUPERVISOR,ROLE_USER" />
        <user name="cpilling04@aol.com.dev" password="testing"
            authorities="ROLE_MEMBER_INQUIRY" />
    </user-service>

    <!-- This filter handles a Single Logout Request from the CAS Server -->
    <b:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter" />
    <!-- This filter redirects to the CAS Server to signal Single Logout should 
        be performed -->
    <b:bean id="requestSingleLogoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter"
        p:filterProcessesUrl="/j_spring_cas_security_logout">
        <b:constructor-arg
            value="https://$cas.server.host/cas-server-webapp/logout" />
        <b:constructor-arg>
            <b:bean
                class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
        </b:constructor-arg>
    </b:bean>

    <b:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"
        p:service="https://$cas.service.host/MemberInquiry/j_spring_cas_security_check"
        p:authenticateAllArtifacts="true" />

    <b:bean id="casEntryPoint"
        class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"
        p:serviceProperties-ref="serviceProperties"
        p:loginUrl="https://$cas.server.host/cas-server-webapp/login" />

    <b:bean id="casFilter"
        class="org.springframework.security.cas.web.CasAuthenticationFilter"
        p:authenticationManager-ref="authManager" p:serviceProperties-ref="serviceProperties"
        p:proxyGrantingTicketStorage-ref="pgtStorage"
        p:proxyReceptorUrl="/j_spring_cas_security_proxyreceptor">
        <b:property name="authenticationDetailsSource">
            <b:bean
                class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource" />
        </b:property>

        <b:property name="authenticationFailureHandler">
            <b:bean
                class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
                p:defaultFailureUrl="/casfailed.jsp" />
        </b:property>


        <b:property name="authenticationSuccessHandler">
            <b:bean
                class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"
                p:defaultTargetUrl="/requests/add.html" />
        </b:property>
    </b:bean>
    <!-- NOTE: In a real application you should not use an in memory implementation. 
        You will also want to ensure to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup() -->
    <b:bean id="pgtStorage"
        class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
    <b:bean id="casAuthProvider"
        class="org.springframework.security.cas.authentication.CasAuthenticationProvider"
        p:serviceProperties-ref="serviceProperties" p:key="casAuthProviderKey">
        <b:property name="authenticationUserDetailsService">
            <b:bean
                class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                <b:constructor-arg ref="userService" />
            </b:bean>
        </b:property>
        <b:property name="ticketValidator">
            <b:bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"
                p:acceptAnyProxy="true"
                p:proxyCallbackUrl="https://$cas.service.host/MemberInquiry/j_spring_cas_security_proxyreceptor"
                p:proxyGrantingTicketStorage-ref="pgtStorage">
                <b:constructor-arg value="https://$cas.server.host/cas-server-webapp" />
            </b:bean>
        </b:property>
        <b:property name="statelessTicketCache">
            <b:bean
                class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
                <b:property name="cache">
                    <b:bean class="net.sf.ehcache.Cache" init-method="initialise"
                        destroy-method="dispose">
                        <b:constructor-arg value="casTickets" />
                        <b:constructor-arg value="50" />
                        <b:constructor-arg value="true" />
                        <b:constructor-arg value="false" />
                        <b:constructor-arg value="3600" />
                        <b:constructor-arg value="900" />
                    </b:bean>
                </b:property>
            </b:bean>
        </b:property>
    </b:bean>

    <!-- Configuration for the environment can be overriden by system properties -->
    <context:property-placeholder
        system-properties-mode="OVERRIDE" properties-ref="environment" />

    <util:properties id="environment">
        <b:prop key="cas.service.host">wcmisdlin07.uftmasterad.org:8443</b:prop>
        <b:prop key="cas.server.host">wcmisdlin07.uftmasterad.org:8443</b:prop>
    </util:properties>


    <b:bean id="contextSource"
        class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">

        <b:constructor-arg
            value="ldaps://dvldap01.uftwf.dev:636/dc=uftwf,dc=dev" />

        <b:property name="userDn" value="cn=Manager,dc=uftwf,dc=dev" />

        <b:property name="password" value="uftwf" />
    </b:bean>

        <b:bean id="ldapAuthProvider"
        class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">

        <b:constructor-arg>

            <b:bean
                class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <b:constructor-arg ref="contextSource" />
                <b:property name="userDnPatterns">
                    <b:list>
                        <b:value>
                            uid=0,ou=webusers
                        </b:value>
                    </b:list>
                </b:property>
            </b:bean>
        </b:constructor-arg>
        <b:constructor-arg>
            <b:bean
                class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
                <b:constructor-arg ref="contextSource" />
                <b:constructor-arg value="ou=groups" />
                <b:property name="groupRoleAttribute" value="ou" />
            </b:bean>
        </b:constructor-arg>
    </b:bean>
    <ldap-server url="ldaps://dvldap01.uftwf.dev:636/dc=uftwf,dc=dev" />




</b:beans>

【问题讨论】:

【参考方案1】:

您需要将内存中的UserDetailsService bean (userService) 替换为LdapUserDetailsService。如果您之前使用 LDAP 进行身份验证,那么配置应该几乎相同,假设 CAS 返回的用户名可以轻松映射到目录中。

更详细地说:您当前有一个名为 userService 的 bean,它是使用命名空间创建的:

<user-service id="userService">
    <user name="rod" password="rod" authorities="ROLE_SUPERVISOR,ROLE_USER" />
    <user name="cpilling04@aol.com.dev" password="testing"
        authorities="ROLE_MEMBER_INQUIRY" />
</user-service>

您需要将其替换为如下所示:

<ldap-user-service id="userService" 
    server-ref="yourLdapServer" 
    user-search-base="ou=people"
    user-search-filter="(uid=0)"
    group-search-base="ou=groups"
    group-role-attribute="cn"
    group-search-filter="(member=0)"
    role-prefix="ROLE_" />

但设置了各种属性以匹配您的目录配置。它们应该类似于您在迁移到 CAS 之前在 &lt;ldap-authentication-provider&gt; 配置中的任何内容。您还需要声明一个&lt;ldap-server&gt; 元素以指向目录服务器。这应该与您之前的相同。

【讨论】:

如果您的意思是使用ldap-user-service,详细信息将在很大程度上取决于您的目录是如何设置的。正如我所说,XML 配置属性应该与您之前的类似。如果您搜索,您会找到示例,例如this one。 对不起,我仍然不明白如何将用户服务更改为我的旧 ldap 服务 卢克。具有所有工作 LDAP 信息的 XML 位于。 docs.google.com/document/d/… 基于此以及您在网站上发布的其他内容,我最好的猜测是您需要设置group-role-attribute="ou" 而不是使用“cn”。通过使用 LDAP 浏览器查看目录结构,您应该可以轻松解决此问题。

以上是关于使用 CAS 进行身份验证和 LDAP 进行授权的 Spring 项目的主要内容,如果未能解决你的问题,请参考以下文章

Shiro 和 CAS 如何使用不同的域进行身份验证和授权?

Apache Shiro - 用于身份验证和属性的 LDAP/用于授权的 Ini

CAS 4 - 成功验证后无法检索 LDAP 组

Spring Security - LDAP 身份验证和数据库授权

使用 Spring Boot/Spring Security 对 LDAP 进行证书身份验证

使用nodejs进行LDAP身份验证