使用 LDAP 验证 Spring Web 服务

Posted

技术标签:

【中文标题】使用 LDAP 验证 Spring Web 服务【英文标题】:authenticating Spring Web Service with LDAP 【发布时间】:2014-10-14 18:42:15 【问题描述】:

我想公开一个使用 LDAP 进行身份验证的示例 Spring Web 服务。 首先,我创建了网络服务:

import javax.jws.WebMethod;
import javax.jws.WebService;

import com.domain.SampleEntity;

/**
* Actual web service implementation.
* 
*/
@WebService
public class SampleEntityWebService 
    /**
    * Read and return SampleEntity by a supplied id.
    */
    @WebMethod
    public SampleEntityByIdResponse readSampleEntityById(Long id) 
        SampleEntity sampleEntity = new SampleEntity();
        sampleEntity.setId(id);
        SampleEntityByIdResponse sampleEntityByIdResponse = new SampleEntityByIdResponse();
        sampleEntityByIdResponse.setSampleEntity(sampleEntity);
        return sampleEntityByIdResponse;
    

Web Service Provider 配置包含:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:ws="http://www.springframework.org/schema/integration/ws"
    xmlns:sec="http://www.springframework.org/schema/security"
    xmlns:sws="http://www.springframework.org/schema/web-services"
    xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws-2.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
        ">

    <!-- TOOD: Check if required or not -->

    <!-- <bean id="simpleJaxWzServiceExporter"
        class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
        <property name="baseAddress" value="$ws.base.url" />
    </bean> -->

    <!-- <context:component-scan base-package="com.integration.ws.provider" /> -->

    <!-- <context:property-placeholder location="classpath:META-INF/spring/web-service.properties" /> -->

    <bean id="sampleEntityMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>com.integration.ws.provider.SampleEntityByIdRequest</value>
                <value>com.integration.ws.provider.SampleEntityByIdResponse</value>
                <value>com.domain.SampleEntity</value>
            </list>
        </property>
    </bean>

    <bean
        class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
        <property name="mappings">
            <props>
                <prop key="$ws.base.url/sampleEntityById">sampleEntity-by-id-gateway</prop>
            </props>
        </property>
        <property name="interceptors">
            <list>
                <ref local="wsSecurityInterceptor" />
            </list>
        </property>
    </bean>  

    **<bean id="wsSecurityInterceptor"
        class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
        <property name="policyConfiguration" value="classpath:META-INF/securityPolicy.xml" />
        <property name="callbackHandlers">
            <list>
                <ref bean="authenticationHandler"/>
            </list>
        </property>
    </bean>**

    <bean id="authenticationHandler"
        class="org.springframework.ws.soap.security.xwss.callback.SpringDigestPasswordValidationCallbackHandler">
          <property name="userDetailsService">
            <bean class="org.springframework.security.core.userdetails.memory.InMemoryDaoImpl">
                <property name="userMap">
                    <value>
                        $wsUserName=$wsUserPassword,ROLE_USER
                    </value>
                </property>
            </bean>
          </property> 
    </bean> 


    <ws:inbound-gateway id="sampleEntity-by-id-gateway"
        request-channel="sampleEntityRequestById" marshaller="sampleEntityMarshaller"
        unmarshaller="sampleEntityMarshaller" reply-channel="sampleEntityResponse" />

    <int:channel id="sampleEntityRequestById" />
    <int:channel id="sampleEntityResponse" />

    <int:service-activator
        expression="@sampleEntityWebService.readSampleEntityById(payload.id)"
        input-channel="sampleEntityRequestById" output-channel="sampleEntityResponse" requires-reply="true"/>

    <int:channel id="sampleEntitys" />

</beans>

引用的安全策略文件包含:

<xwss:SecurityConfiguration dumpMessages="true" xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"> 
    <xwss:RequireUsernameToken passwordDigestRequired="true" nonceRequired="true"/> 
    </xwss:SecurityConfiguration>

该服务运行良好。现在我想对使用 LDAP 访问此服务的用户进行身份验证。 我是 Spring Web 服务和安全性的新手。谁能建议将 Spring Web 服务与 LDAP 集成所需的配置更改。

【问题讨论】:

【参考方案1】:

您可以将用户详细信息服务从InMemoryDaoImpl 更改为LdapUserDetailsService

我能推导出的配置是:

<bean id="contextSource"
        class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
  <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
  <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
  <property name="password" value="password"/>
</bean>

<bean id="ldapPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
   <constructor-arg ref="contextSource"/>
   <constructor-arg value="ou=groups"/>
   <property name="groupRoleAttribute" value="ou"/>
</bean>

<bean id="userSearch"
    class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg index="0"
        value="ou=People,o=MyCompany,o=Intranet" />
    <constructor-arg index="1" value="(uid=0)" />
    <constructor-arg index="2" ref="contextSource" />
</bean>

<bean id="authenticationHandler" class="org.springframework.ws.soap.security.xwss.callback.SpringDigestPasswordValidationCallbackHandler">
      <property name="userDetailsService">
        <bean class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
             <constructor-arg ref="userSearch">
             <constructor-arg ref="ldapPopulator">
        </bean>
      </property> 
</bean> 

请记住,我还没有尝试过,而且大部分部分都是我从其他来源复制的。您需要的是UserDetailsService,您只需将其设置为authenticationHandler。从LdapUserDetailsService 源代码来看,它需要两个构造函数,LdapUserSearchLdapAuthoritiesPopulator。我搜索了一个关于如何实例化LdapUserSearch bean 的示例,并从here 中找到了示例。我从官方文档中找到了 LdapPopulator bean 示例。

有关使用 Spring Security 的 Ldap 身份验证的更多详细信息,请访问official documentation。

希望您了解 LDAP,因为我对 LDAP 一无所知。祝你好运。

【讨论】:

以上是关于使用 LDAP 验证 Spring Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security Active Directory LDAP 身份验证错误

Spring 安全切换到 Ldap 身份验证和数据库权限

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

使用 jboss 安全域的 LDAP 身份验证

在 Spring Security(spring-boot 项目)中使用 ldap 凭据进行 Http 基本身份验证以保护休息服务调用

Spring boot Ldap 身份验证失败,LDAP 错误代码 49 - 80090308 数据 52e