如何在春季测试 LDAP 安全配置?

Posted

技术标签:

【中文标题】如何在春季测试 LDAP 安全配置?【英文标题】:How to test LDAP security configuration in spring? 【发布时间】:2021-08-20 00:12:12 【问题描述】:

如何为spring-boot 中的ldap 安全配置编写测试?

身份验证管理器首先验证用户姓名首字母是否存在于 ldap 中,并且找到的用户是 memberOf 为用户过滤器设置的任何组。

问题:我怎么能模拟 ldap 响应?例如,我想返回一个带有memberOf=CN=Team-INVALID 的用户,它不应该是测试范围内的身份验证。 我当然想返回一个与userSearchFilter 匹配的用户。

但是我必须为这个测试模拟哪个类?

@Configuration
@Order(1)
@EnableWebSecurity
public class LdapSecurityConfiguration extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.ldapAuthentication()
            .userSearchFilter("(&(initials=0)(|" +
                    "(memberOf=CN=TEAM-1,OU=Intern,DC=my-company)" +
                    "(memberOf=CN=TEAM-2,OU=Intern,DC=my-company)" +
                    "))")
            .contextSource()
            .url(ldapUrl + ldapBase)
            .managerDn(ldapUsername)
            .managerPassword(ldapPassword);
    

【问题讨论】:

为什么要测试 spring 很可能已经测试过的东西?如果您想测试您的配置是否有效,请测试 ldapauthentication 流程。我不知道用户如何在您的应用程序中进行身份验证,因为您没有提供该代码 我只是想测试我的自定义userSearchFilter()。不是一般的ldap spring。那么如果不模拟真实的 ldap 服务器响应,我该如何测试呢? 也许可以尝试使用docs.spring.io/spring-security/site/docs/current/reference/…,然后测试您的身份验证流程。如果用户可以进行身份​​验证,则您的搜索过滤器有效,如果他无法进行身份验证,则它不起作用。 好吧,这不是一个解决方案。想象一下,您想要测试使用数据库结果的工作流。而不是模拟 sql 结果,而是添加一个内存数据库。这一步太远了…… 这不是一步之遥,绝对不是。如果您的查询有效,唯一可以肯定回答的是 LDAP 的正确实现。如果你模拟,你基本上是在估计,如果你模拟错误并且你的测试通过了,你的测试会给你一个更危险的误报。 LDAP 实现不会撒谎,特别是如果您在测试中使用与生产中使用的相同 LDIF。您想要对 LDAP 集成进行单元测试。单元测试是针对单元的。集成测试用于集成。 【参考方案1】:

您可以为您的测试定义一个带有 LDIF 文件的嵌入式 LDAP 服务器,如下所示:

spring.ldap.embedded.ldif=classpath:test-server.ldif
spring.ldap.embedded.base-dn=dc=springframework,dc=org
spring.ldap.embedded.port=8389

在您的测试中,您可以尝试像在正常流程中那样对特定用户进行身份验证:

@SpringBootTest
@AutoConfigureMockMvc
@TestPropertySource(properties = 
        "spring.ldap.embedded.ldif=classpath:test-server.ldif",
        "spring.ldap.embedded.base-dn=$spring.ldap.base",
        "spring.ldap.embedded.port=8389",
        "spring.ldap.embedded.url=ldap://localhost:8389/",
        "spring.ldap.embedded.credential.username=uid=admin",
        "spring.ldap.embedded.credential.password=secret",
        "spring.ldap.embedded.validation.enabled=false",
        "spring.ldap.urls=ldap://localhost:8389/",
        "spring.ldap.username=uid=admin",
        "spring.ldap.password=secret")
public class AuthenticatingLdapApplicationTests 
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void loginWithValidUserThenAuthenticated() throws Exception 
        FormLoginRequestBuilder login = formLogin()
            .user("user")
            .password("userpassword");

        mockMvc.perform(login)
            .andExpect(authenticated().withUsername("user"));
    

    @Test
    public void loginWithInvalidUserThenUnauthenticated() throws Exception 
        FormLoginRequestBuilder login = formLogin()
            .user("invalid")
            .password("invalidpassword");

        mockMvc.perform(login)
            .andExpect(unauthenticated());
    

我在Authenticating with LDAP Guide 中找到了这个示例。您可以参考它以获取更多详细信息

需要的依赖:

<dependency>
    <groupId>com.unboundid</groupId>
    <artifactId>unboundid-ldapsdk</artifactId>
    <version>5.1.4</version>
    <scope>test</scope>
</dependency>

【讨论】:

如何强制将application.properties 中的现有ldap 替换为嵌入的用于测试的ldap? 在您的测试文件夹中,您可以创建一个application.properties 文件甚至application-test.properties 并使用@ActiveaProfiles("test") 运行您的测试 我必须添加 unboundid-ldapsdk 库才能使其正常工作。此外,我必须配置spring.ldap.embedded.*,然后将我的主要spring.ldap.* 属性路由到嵌入式连接。将使用所需的测试属性更新您的示例。

以上是关于如何在春季测试 LDAP 安全配置?的主要内容,如果未能解决你的问题,请参考以下文章

OAuth2用户详细信息未在春季安全(SpringBoot)中更新

如何使用 xml 配置文件、JAVA、Spring 安全性对 LDAP 用户进行身份验证

春季安全+休息不起作用

Spring 安全性、ssl ldap 和无证书

春季安全oauth2返回404

MockMVC - 如何使用 org.hamcrest.Matcher 在春季安全集成测试中检查 JWT 令牌的内容