在Java应用程序中保存用户设置的最佳方式是什么?

70

什么是在Java桌面应用中安全地保存用户设置的最佳方式?例如,如果我想保存FTP帐户设置,最好的方法是什么?

谢谢

3个回答

58

14
我们应该把所需的密钥存储在哪里? - Cheok Yan Cheng
6
这是一个不错的入门教程:http://www.mkyong.com/java/java-properties-file-examples/ 它介绍了Java属性文件的例子。 - james.garriss
我想提醒一下,在Windows系统上,如果您正在使用“首选项”,您可能需要更改注册表。对于您的应用程序的普通用户来说,这可能是一个障碍(不可行!)。 - El Mac
@ElMac:我猜你指的是臭名昭著的“警告:无法打开/创建首选项根节点Software\JavaSoft\Prefs,位于根0x80000002处。Windows RegCreateKeyEx(...)返回错误代码5”的警告?这导致用户认为他们需要使用regedit创建一个新的Win注册表键(因为这样警告就消失了)。实际上,这是Java本身的一个bug。你不应该这样做。这是一个bug的结果。 - peterh

27

我通常将数据存储在用户数据目录中,应用程序名称后跟应用程序版本的子目录中。

public static String getUserDataDirectory() {
    return System.getProperty("user.home") + File.separator + ".jstock" + File.separator + getApplicationVersionString() + File.separator;
}

我已经使用以下代码三年了。这种方法在Windows、Linux或Mac上都非常有效。

请注意,在Windows中,永远不要将它存储在Program Files中,因为Windows Vista或更高版本中的UAC可能会给您带来很多麻烦。

记得在你的应用程序名称前面加一个点,这样它就会成为Linux中的隐藏文件夹。

使用这种方式的好处是,你不仅可以存储基本类型,还可以使用xstream将整个对象状态保存到磁盘中。

例如:

public static boolean toXML(Object object, File file) {
    XStream xStream = new XStream();
    OutputStream outputStream = null;
    Writer writer = null;

    try {
        outputStream = new FileOutputStream(file);
        writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-8"));
        xStream.toXML(object, writer);
    }
    catch (Exception exp) {
        log.error(null, exp);
        return false;
    }
    finally {
        close(writer);
        close(outputStream);
    }

    return true;
} 

但这安全吗?你是以明文形式存储密码吗? - djna
1
有时候将密码以明文形式存储是有道理的,而不是仅仅混淆它们——混淆只会给人一种虚假的安全感。例如,请参见http://developer.pidgin.im/wiki/PlainTextPasswords - gustafc
在存储密码之前,我会使用http://www.jasypt.org/进行加密。目前,我在应用程序中硬编码了我的加密密钥。我曾经考虑让用户指定密钥。然而,这可能会阻止普通用户使用我的应用程序,因为很难解释密钥是什么。因此,我放弃了这个想法。到目前为止,我没有收到任何关于安全问题的投诉。 - Cheok Yan Cheng
6
那么任何拥有你的程序副本的人都可以使用任何人的密钥文件吗?缺乏投诉并不意味着安全。密码被窃取的人可能甚至没有意识到这一事实。当然,这是可行的,并且在受到适当保护的计算机上风险非常低,但实际上加密带来的好处很少。实际上,你的应用程序就是密钥,因此需要加以保护。 - djna
4
我认为这是一个安全威胁,因为黑客可以通过反编译您的Java代码获取硬编码密码。 - Feras Odeh
这不是在Windows上存储用户或应用程序数据的位置。 - Cypher

13

安全地存储单个密码非常困难。假设您使用某些秘密密钥对密码进行加密。那么当应用程序再次启动时,它需要该秘密密钥,它从哪里获取?

如果它要求用户提供,则用户可能就像在第一次存储ftp密码时输入密码。如果它从某处读取秘密密钥,则需要保护秘密密钥,我们又回到了起点。

如果您保存了多个密码,则要求用户为某个“保险库”提供一个密码可能更加友好,但接下来您将面临处理过期密码的所有麻烦。

有一些产品可供处理此类事情,如果您有严重的需求,则可能需要调查它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接