2

我有一个包含多个properties文件的应用程序,我很好奇将这些 // 组合存储在 JNDI 查找中而不是在 .jar 中存储username这个明文文件是否更容易passwordserver-url-to-login-to

有几个问题:

  1. 您可以使用 JNDI 存储不是数据库的凭据吗?
  2. 如何配置新的 JNDI 资源来存储这些属性?
  3. 您将如何从资源中检索这些属性?

我阅读的大部分文档是如何为数据库连接设置 JNDI,对于我的使用,我没有连接到任何数据库,而是使用不同的身份验证方案(请求消息中的 SOAP 用户/密码, HTTP Basic、标头、SSL 等)。

4

1 回答 1

3

您的问题的答案:

  1. 您可以使用 JNDI 存储不是数据库的凭据吗?

是的。

  1. 如何配置新的 JNDI 资源来存储这些属性?

如果您使用的是 Glassfish 2,则必须创建自定义PropertiesObjectFactory类来JNDI处理java.util.Porperties.

例如,PropertiesObjectFactory类可能如下所示:

public class PropertiesObjectFactory implements Serializable, ObjectFactory {

    public static final String FILE_PROPERTY_NAME = "org.glassfish.resources.custom.factory.PropertiesFactory.fileName";

    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
            throws Exception {
        Reference ref = (Reference) obj;
        Enumeration<RefAddr> refAddrs = ref.getAll();

        String fileName = null;
        Properties fileProperties = new Properties();
        Properties properties = new Properties();

        while (refAddrs.hasMoreElements()) {
            RefAddr addr = refAddrs.nextElement();
            String type = addr.getType();
            String value = (String) addr.getContent();

            if (type.equalsIgnoreCase(FILE_PROPERTY_NAME)) {
                fileName = value;
            } else {
                properties.put(type, value);
            }
        }

        if (fileName != null) {
            File file = new File(fileName);
            if (!file.isAbsolute()) {
                file = new File(System.getProperty("com.sun.aas.installRoot") + File.separator + fileName);
            }
            try {
                if (file.exists()) {
                    try {
                        FileInputStream fis = new FileInputStream(file);
                        if (fileName.toUpperCase().endsWith("XML")) {
                            fileProperties.loadFromXML(fis);
                        } else {
                            fileProperties.load(fis);
                        }
                    } catch (IOException ioe) {
                        throw new IOException("IO Exception during properties load : " + file.getAbsolutePath());
                    }
                } else {
                    throw new FileNotFoundException("File not found : " + file.getAbsolutePath());
                }
            } catch (FileNotFoundException fnfe) {
                throw new FileNotFoundException("File not found : " + file.getAbsolutePath());
            }
        }
        fileProperties.putAll(properties);
        return fileProperties;
    }
}

制作一个该类的罐子,将其添加到 glassfish 全局类路径中。它将是:/glassfish/domains/domain1/lib然后您可以在JNDI属性配置中将其指定为工厂类。

Glassfish 3 已经有属性工厂类。它设置为:org.glassfish.resources.custom.factory.PropertiesFactory

打开 glassfish 管理控制台并导航到:资源 -> JNDI -> 自定义资源,单击“新建”,提供 JNDI 名称,例如:jndi/credentials,选择资源类型java.util.Properties,指定工厂类:org.glassfish.resources.custom.factory.PropertiesFactory,然后单击“添加属性”,指定名称例如:testUsernameName在值列testUsernameValue中。单击确定,就是这样,您已经配置了JNDI资源。您可以根据需要添加任意数量的属性:jndi/credentials资源。

完成资源创建后不要忘记重启应用服务器。

  1. 您将如何从资源中检索这些属性?
public Properties getProperties(String jndiName) {
    Properties properties = null;
    try {
        InitialContext context = new InitialContext();
        properties = (Properties) context.lookup(jndiName);
        context.close();
    } catch (NamingException e) {
        LOGGER.error("Naming error occurred while initializing properties from JNDI.", e);
        return null;
    }
    return properties;
}

示例如何获取属性:

String username = someInstance.getProperties("jndi/credentials").getProperty("testUsernameName"); 

username会是:testUsernameValue

当您在应用程序中调用此方法时,请提供JNDI您在应用程序服务器中配置的名称:jndi/credentials. 如果您在部署描述符中映射了资源,则必须使用:java:comp/env/jndi/credentials.

如果您想使用以下方法执行相同操作Spring

<jee:jndi-lookup id="credentials"
                 jndi-name="jndi/credentials"/>

好吧,我希望就是这样。希望这可以帮助。

于 2012-10-18T10:35:02.627 回答