Spring,属性文件,空值

时间:2012-05-07 13:34:19

标签: spring spring-security placeholder

我已经使用ldap服务器配置了spring security(但是继续阅读,如果你不了解它就不是问题,这真的是一个春天的问题)。所有的运行都像一个魅力。这是我用于此的行:

<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" />

to(通过删除对变量$ {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不会用属性config替换属性值。但我觉得很奇怪。

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

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

5 个答案:

答案 0 :(得分: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},依此类推。

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

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

当使用创建的源时,它将用空值替换$ {ldap.server.url}(如属性文件中指定的那样)。并且....... Bug!

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

答案 1 :(得分:1)

我无法解释,但我认为您可以使用默认语法修复您的问题,自Spring 3.0.0.RC1(see)以来可用。

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

我认为使用占位符时存在问题。以下内容最有可能解决问题:

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

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

希望这有帮助。

答案 4 :(得分:0)

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

com.core.estimation.stopwords = \ \ enter image description here