10

我已经用ldap服务器配置了spring security(但是继续阅读,如果你不了解它也不是问题,这确实是一个spring问题)。一切都像魅力一样运行。这是我用于此的行:

<ldap-server ldif="" root="" manager-dn="" manager-password="" url=""  id="ldapServer" />

如果我填写 ldif 和 root 属性,它将运行一个嵌入式服务器:

<ldap-server ldif="classpath://ldap.ldif" root="dc=springframework,dc=org" manager-dn="" manager-password="" url=""  id="ldapServer" />

如果我填写其他字段,它将运行一个远程服务器:

<ldap-server ldif="" root="" manager-dn="dc=admin,dc=springframeworg,dc=org" manager-password="password" url="ldap://myldapserver.com/dc=springframeworg,dc=org" id="ldapServer" />

所有这些东西都运行正常。现在我想使用 Spring 机制从属性文件中加载这些参数:

所以我像这样替换属性值:

<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="${ldap.server.url}"  id="ldapServer" />

并创建一个属性文件:

ldap.server.url=
ldap.server.manager.dn=
ldap.server.manager.password=

ldap.ldif.path= 
ldap.ldif.root= 

现在,问题的有趣部分。如果我在文件中填写以下属性:

ldap.server.url=ldap://myldapserver.com/dc=springframeworg,dc=org
ldap.server.manager.dn=dc=admin,dc=springframeworg,dc=org
ldap.server.manager.password=password

ldap.ldif.path= 
ldap.ldif.root= 

它按预期运行远程服务器。

如果我像这样填写属性文件:

ldap.server.url=
ldap.server.manager.dn=
ldap.server.manager.password=

ldap.ldif.path= classpath:ldap.ldif
ldap.ldif.root= dc=springframeworg,dc=org

它没有运行,抱怨缺少 ldap url。但问题是,如果我从以下位置更改弹簧配置:

<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="${ldap.server.url}"  id="ldapServer" />

到(只需删除对变量 ${ldap.server.url} 的引用)

<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url=""  id="ldapServer" />

它运行!

我的想法是,如果该属性值为空,则 spring 不会将属性值替换为属性配置之一。但我觉得很奇怪。

你能给我一些线索来理解吗?通过属性文件配置我的 ldap 服务器的最佳方法是什么?

编辑:这是由于设计选择不佳(查看接受的答案),在 jira 上打开了一个问题: https ://jira.springsource.org/browse/SEC-1966

4

5 回答 5

2

好的,我认为这是一个弹簧安全错误。

如果我调试并查看 LdapServerBeanDefinition 类,有一个名为“parse”的方法。这是一个摘录:

public BeanDefinition parse(Element elt, ParserContext parserContext) {
    String url = elt.getAttribute(ATT_URL);

    RootBeanDefinition contextSource;

    if (!StringUtils.hasText(url)) {
        contextSource = createEmbeddedServer(elt, parserContext);
    } else {
        contextSource = new RootBeanDefinition();
        contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS);
        contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url);
    }

    contextSource.setSource(parserContext.extractSource(elt));

    String managerDn = elt.getAttribute(ATT_PRINCIPAL);
    String managerPassword = elt.getAttribute(ATT_PASSWORD);

    if (StringUtils.hasText(managerDn)) {
        if(!StringUtils.hasText(managerPassword)) {
            parserContext.getReaderContext().error("You must specify the " + ATT_PASSWORD +
                    " if you supply a " + managerDn, elt);
        }

        contextSource.getPropertyValues().addPropertyValue("userDn", managerDn);
        contextSource.getPropertyValues().addPropertyValue("password", managerPassword);
    }

    ...
}

如果我在这里调试,所有变量(url、managerDn、managerPassword...)都不会被属性文件中指定的值替换。因此,url 的值为 ${ldap.server.url},managerDn 的值为 ${ldap.server.manager.dn},依此类推。

方法 parse 创建一个 bean,一个将被进一步使用的上下文源。当这个 bean 被使用时,占位符将被替换。

在这里,我们得到了错误。parse 方法检查 url 是否为空。问题是这里的 url 不是空的,因为它的值是 ${ldap.server.url}。因此,parse 方法创建了一个上下文源作为远程服务器。

当使用创建的源时,它会将 ${ldap.server.url} 替换为空值(如属性文件中指定的)。而且.......错误!

我现在真的不知道如何解决这个问题,但我现在明白为什么它会出错;)

于 2012-05-28T08:02:21.510 回答
1

我无法解释它,但我认为您可以使用自 Spring 3.0.0.RC1 起提供的默认语法来解决您的问题(请参阅参考资料)。

在 chageg 日志中,您可以阅读:PropertyPlaceholderConfigurer 支持“${myKey:myDefaultValue}”默认语法

无论如何,我认为问题在于“”是有效值,但属性文件中没有值。

于 2012-05-07T17:50:03.757 回答
1

我认为这是url=""有效的,因为url属性是xs:tokenspring-security XSD 中的类型,并且空字符串被转换为nullxs:token正在删除任何前导或尾随空格,因此""可以被识别为无值)。也许 的值${ldap.server.url}被解析为空字符串,这就是您遇到错误的原因。

您可以尝试使用 Spring 配置文件来定义 ldap 服务器的不同配置(有关配置文件的详细信息,请参阅Spring 团队博客

于 2012-05-25T12:53:52.030 回答
1

我相信在使用占位符时存在问题。以下最有可能解决问题:

创建一个扩展 PropertyPlaceHolderConfigurer 的类,并在该方法中覆盖其方法 convertPropertyValue() 如果您发现除 LDAP url 类型的字符串以外的任何内容(即 ldap://myldapserver.com/dc=springframeworg),您可以将属性作为空字符串返回,dc=org

您还需要在上下文文件中配置类 PropertyPlaceHolderConfigurer 的新专业化。

希望这可以帮助。

于 2012-05-28T07:44:32.320 回答
0

String您可以在文件中定义空,application.properties如下所示:

com.core.estimation.stopwords=\ \ 在此处输入图像描述

于 2020-02-06T04:33:11.973 回答