Java 为什么不使用DriverManager.getConnection(字符串url、字符串用户、字符[]密码)?

Java 为什么不使用DriverManager.getConnection(字符串url、字符串用户、字符[]密码)?,java,security,string,char,Java,Security,String,Char,我们知道,最好使用char[]而不是java.lang.String来存储密码。这是因为以下两个原因(正如我所读到的): char[]是可变的,因此我们可以在使用后清除密码 字符串文本进入一个池,该池不会像其他对象一样被垃圾收集,因此可能会出现在内存转储中 但是java.sql.DriverManager没有符合上述最佳实践的getConnection(),因为它的密码参数是String getConnection(字符串url、字符串用户、字符串密码) 我认为API应该具有具有以下签名的重载方

我们知道,最好使用char[]而不是java.lang.String来存储密码。这是因为以下两个原因(正如我所读到的):

  • char[]是可变的,因此我们可以在使用后清除密码
  • 字符串文本进入一个池,该池不会像其他对象一样被垃圾收集,因此可能会出现在内存转储中
  • 但是java.sql.DriverManager没有符合上述最佳实践的getConnection(),因为它的密码参数是String

    getConnection(字符串url、字符串用户、字符串密码)

    我认为API应该具有具有以下签名的重载方法:

    getConnection(字符串url,字符串用户,char[]密码)

    你觉得这个怎么样?你有没有其他办法来克服这种倒退


    我很想听听你的想法。

    字符串文字放在池中,但我不希望密码是文字(在程序中硬编码)。我希望它来自一个配置或类似的配置。因此,它不会是一个文本,并且会被垃圾收集(前提是所有引用都被装箱)。

    人们只能猜测,除非您可以询问API的设计者

    我的猜测是:

    我所知道的密码使用
    char[]
    而不是
    String
    的主要API是。这样做是为了允许程序在使用值后用其他值覆盖用户输入的密码(这在
    字符串
    中是不可能的,它至少会在内存中保留到垃圾收集为止)

    在我知道的大多数应用程序中,用于连接数据库的密码通常不是用户输入的,而是来自某种配置/目录/

    不管它来自何处:应用程序能够在不再知道它时重新构造它。这是用户输入的密码和程序获取的密码之间的巨大区别

    <>因为密码通常可以比搜索程序所使用的所有内存都容易获取,所以修复这个攻击向量不是一个高优先级


    您的理由#2是我见过的最常用于在字符串上使用char[]的理由。但是,一般来说,我认为如果您假设有人可以通过调试器或其他方式访问您的程序状态,那么他们没有理由不能同时查看char[]的内容

    使用char[]数组的参数最适用于用户键入密码的地方,并且您希望尽量减少该密码的暴露

    JDBC连接几乎从来都不是这样。密码存储在某个配置文件中,可能已经混淆,并且是比读取内存的可能性大得多的泄漏源

    无论如何,JDBC标准允许在属性对象甚至URL中传递密码,因此我认为使用
    char[]
    password参数会给您一种错误的安全感


    如果您有一个真实的用例,其中密码需要尽快从内存中删除以使其不可恢复,否则在真实的JDBC应用程序上下文中是有意义的,我很乐意听到它。我可以想象这样的事情可能存在,但我想不出使用
    char[]
    真的能让事情更安全的场景。

    您的第1点在某种程度上是有效的,但是关于字符串最终进入未收集字符串池的第2点只适用于静态文本字符串(直接出现在代码中的字符串)。如果您的代码中直接存储了密码,我建议您首先考虑这些问题,因为在类文件中查找密码要比在运行的VM中查找密码容易得多

    因此,如果您认为必须将密码存储在char[]中,您仍然可以在调用getConnection()之前从中创建字符串对象。如果驱动程序实现不在内部存储字符串对象,它将很快无法访问,因此很快就会被收集。当时仍然阅读它的唯一机会是直接检查JVM内存中可能仍然存在的位置。因此,您是对的,使用char[]会更安全一些,但无论如何也不会像密码在某个时候必须在内存中那样安全


    也就是说,使用任何类型的API获取密码的一种非常简单的方法是注入伪造的SQL驱动程序,并直接在connect方法中获取密码。无论谁能够检查JVM内存,在内存中找到一个尚未被覆盖的密码字符串,他也可以插入一个修改过的驱动程序jar。

    你说得很好,大多数回答的人都没有找到它。最坏的情况是操作系统以明文形式将“临时”密码调出。在此之后,这个交换文件很容易读取,如果攻击者拥有大约1500美元的设备,磁盘上的交换文件甚至可以被零覆盖

    最好是连接,password=null,然后显式调用gc()。如果幸运的话,这将清除驱动程序实现使用的字符串

    无论如何

    • 你所要求的目前是不可能的,但会很好
    • 即使是char[]也可以在某些条件下生存(例如交换)
    • 您的密码在进入数据库的过程中会被多次复制,因此char[]只解决了问题的一部分

    现实是,除非平台是专门为安全而设计的,否则所有方法都只是拖延战术。尽你所能,但如果有决心的人可以访问你的机器,char[]最多可以为你赢得1小时。

    关于JDBC的可插拔特性如何让你很容易用自己的驱动程序替换数据库的驱动程序,这是一个很好的观点。关于“JDBC连接几乎从来都不是这样”的有趣注释。我来找这个话题是因为在我们的