要设置哪个权限,以避免使用 https-URLS 的安全管理器出错?

2022-09-04 20:20:52

在客户的软件中,我们必须读取给定的URL来解析其内容。此外,客户需要激活 Tomcat-Security-Manager,让 Java-Policies 控制程序的功能。

现在,通过读取URL,异常“javax.net.ssl.SSLKeyException:RSA premaster secret error”会发生,但仅限于某些条件:

  • 如果 URL 是 HTTPS,但不是 HTTP
  • 如果安全管理器已激活,而不是在停用时激活,或者在全局授权中阻止所有权限已设置
  • 仅使用 Java 6,而不是 Java 7(客户目前需要 Java 6)
  • 仅使用Tomcat6,而不是Tomcat 7(客户目前需要Tomcat 6)

安全违规发生在Java代码中的某个地方,仅限于我们的代码库的AllPermission并不能防止错误。

那么,有人有想法,为Java 6设置哪个权限,以便它可以处理HTTPS?

其他信息:它运行在tomcat中,在带有OpenJDK的Debian-Linux上。

编辑:我在变量JAVA_OPTS中将Java-Param“-Djava.security.debug=access,failure”添加到Tomcats /etc/default/tomcat6中。但是在日志中,我没有其他消息。代码是否有可能在触发权限之前询问权限?

编辑2:我找到了正确的地方,并得到了完整的堆栈跟踪(删除了特定的客户部件):

javax.net.ssl.SSLKeyException: RSA premaster secret error

            at [...]
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at javax.security.auth.Subject.doAsPrivileged(Subject.java:537)
            at java.lang.Thread.run(Thread.java:701)
    Caused by: java.security.NoSuchAlgorithmException: SunTlsRsaPremasterSecret KeyGenerator not available
            at javax.crypto.KeyGenerator.<init>(KeyGenerator.java:141)
            at javax.crypto.KeyGenerator.getInstance(KeyGenerator.java:191)
            ... 14 more

编辑3:到目前为止,我假设Java类URL用于访问资源的内容。但这是不真实的。它使用来自Grails-Code的Groovy-URL-object和getText()-方法:

new URL(params.url).text

此行上发生错误。这是Grails版本2.2.4。


答案 1

经过几条评论和OP确认解决方案的解决方案(摘要)

根本原因是存在于多个位置。这是OP在被建议为许多可能的根本原因之一之后发现的(请参阅本答案的末尾和注释线索)。根据OP的评论:sunjce_provider.jar

我在多个目录中有sunjce_provider.jar。我试图为Java 6的所有三个位置提供权利,尽管显然只有一个位置JAVA_HOME - 并且它有效。以某种方式使用了其他位置之一,尽管它不在java.ext.dirs-property中

因此,在这种情况下,解决方案是确保应用程序有权访问正确的副本sunjce_provider.jar

我留下了我最初答案的要点,以及下面帮助诊断的评论,供以后发现这一点的任何人使用。

导致解决方案的原始答案和评论

  1. 这不会发生,因为你的 Web 应用(即此连接的客户端,即使它在 tomcat 中运行)不需要在此配置中生成密钥。http

  2. 它仅在启用 SecurityManager 时发生,但在禁用或使用全局 AllPermission 时不会发生,这表明这是一个文件权限错误。这表明这不是密钥长度的问题(例如,这里提到的那个)

网络上的其他类似报告表明,可能的根本原因是缺少一个罐子(通常引用了sunjce_provider.jar)。堆栈跟踪确认根本原因异常是 正在寻找算法但找不到它的位置。在您的情况下,由于这仅发生在特定配置中,因此它可能是一个无法访问的jar(由于安全权限)。NoSuchAlgorithmExceptionKeyGeneratorSunTlsRsaPremasterSecretSecurityManager

我的猜测是,您尚未启用对包含 RSA 注册机算法所需的 jar 的正确目录的权限。我建议的操作过程是遍历 webapp 和 JRE 目录结构,以查找运行时 jar 的保存位置,并确保它们具有 中 ed 的权限。grant codeBasegrantcatalina.policy

例如,在默认配置中,您应该在某个地方看到

// These permissions apply to all shared system extensions
grant codeBase "file:${java.home}/jre/lib/ext/-" {
        permission java.security.AllPermission;
};

有关这究竟意味着什么的详细信息,请参阅tomcat安全管理器“How To”的这一部分。您需要检查一些事情 - 确保这是您的运行时jar的位置。如果没有 - 更改路径以指向正确的位置(这是我的OpenJDK 6版本 - build 27上的位置)。特别是你应该看到并在那里。确保策略文件中存在上述部分。${java.home}/jre/lib/ext/sunjce_provider.jarsunpkcs11.jar

代码可能依赖于Web应用程序中的某些jar - 例如在 - 在这种情况下,您需要授予对该目录的权限。${catalina.base}/path/to/your/webapp/WEB-INF/classes/


导致相同或类似症状的其他问题

  1. 无法找到或访问的应用程序将给出相同的错误消息(在Ubuntu + openjdk6 + tomcat6系统上验证)。该罐子的重复副本也可能如此。sunpkcs11.jar

  2. 检查。它应该在那里列出提供程序 - 检查那里有一行类似的东西 - 如果缺少该行,你也会收到此错误(在同一系统上验证)/etc/java-6-openjdk/security/java.securitysecurity.provider.n = sun.security.pkcs11.SunPKCS11

  3. 这个 Debian bug 报告讨论了在SecurityManager


调试注释

根据另一个答案,您可以尝试添加到 catalina.sh 中以启用调试 - 默认情况下,调试应记录到(或您在 catalina.sh 中将日志记录设置为 via 的任何位置)。您应该从那里看到输出。-Djava.security.debug=access,failureCATALINA_OPTSJAVA_OPTScatalina.outCATALINA_OUTSecurityManager

你也可以尝试catalina.out',但你可以选择可能有帮助的单词(比如“fail”!!!)-Djava.security.debug=all. You will get a huge


按照堆栈跟踪中的代码进行操作

您的异常被抛出到此处。查看如何引发该异常 - 此方法必须返回 null。它吞噬了 Exceptions - 这并不好,并且很难准确诊断该代码的哪一部分失败。我的钱将在这个行上 - canUseProvider()可能会返回的地方。这一切都指向由于某种原因,提供者jar是不可解密的。false

我假设您在输出中没有看到任何访问冲突,即使使用 .你可以试试,尽管这很可能只产生更多不相关的日志记录。如果没有访问冲突,则您的类路径上可能以某种方式有该 jar 的两个版本,并且运行时正在访问(或尝试访问错误的 jar)。本问答中描述了与此类似的情况。-Djava.security.debug=access,failure-Djava.security.debug=all


答案 2

发现所有必需权限的简单方法是使用参数运行

-Djava.security.debug=access,failure

然后,您将获得有关每个失败的安全访问,有效的保护域等的完整信息。


推荐