0

如果 Tomcat 服务器(在 Linux 上)以 client-authentication=on (org.jboss.web.connector.ssl.client-auth=true) 运行,那么客户端 (OSX 1.7.3) 可以下载 JNLP(在浏览器中),但是 java-webstart 不能下载任何东西,甚至 JNLP 也不能,只显示一个空的证书选择对话框。

证书是自签名的。CA 和客户端证书被导入 OSX 的 KeyChain (ca->system, client+key->login)

调试问题似乎是苹果的 JNLP Java 接口试图以错误的方式到达 OSX 的 KeyChain 密钥库,没有密码(*参见下面的示例)

我基于调试JNLP下载(在OSX上)上的运行代码制作了一个小程序。

import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.X509KeyManager;

public class OSXKeyChainTest {

/**
 * Demonstrating issue in OSX-JNLP-Java interface, the keys from the
 * KeyChain are not accessed during JNLP downloading phase. But if it would
 * use any password it would work (see the FIXME line). This small test
 * program is based on the debugging works on OSX 1.7.3.
 */
public static void main(String[] args) throws Exception {

    KeyStore ks = KeyStore.getInstance("KeyChainStore", "Apple");
    ks.load(null, new char[0]);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509", "SunJSSE");

    // FIXME !!!! try it with ANY password, and it will work, eg. = new char[] {'x'};
    char[] password = new char[] {};

    // as AppleX509DeployKeyManager.getBrowserKeyManager() does
    keyManagerFactory.init(ks, password);

    X509KeyManager localX509KeyManager = null;
    KeyManager[] arrayOfKeyManager = keyManagerFactory.getKeyManagers();

    int i = 0;
    while (i < arrayOfKeyManager.length) {
        if ((arrayOfKeyManager[i] instanceof X509KeyManager)) {
            localX509KeyManager = (X509KeyManager) arrayOfKeyManager[i];
            break;
        }

        i++;
    }

    for (Enumeration<String> t = ks.aliases(); t.hasMoreElements();) {
        String alias = t.nextElement();
        System.out.println("@Alias: " + alias);
        if (ks.isKeyEntry(alias)) {
            System.out.println("It's a key entry");
            for (Certificate c : ks.getCertificateChain(alias)) {
                X509Certificate x509 = (X509Certificate) c;
                System.out.println(x509.getSubjectDN().toString());
                System.out.println("SN: " + x509.getSerialNumber());
            }

            // as SunX509KeyManagerImpl does
            Key localKey = ks.getKey(alias, password);
            System.out.println("Localkey: " + localKey);
        }
    }

    System.out.println("--------------------------------");
    System.out.println("It should be not null!: " + localX509KeyManager.getPrivateKey("client"));
}

}
4

1 回答 1

0

不确定这是否能解决您的问题,但您应该注意以下几点:

  • KeychainStore旨在使用任何密码。

    实际授权应该由 OSX 的安全守护进程处理。当您要使用私钥时,应该会出现一个弹出窗口并询问类似“您要允许此应用程序使用此私钥签名吗?”的内容。如果你没有得到这样的提示,你可能已经授权应用程序在没有提示的情况下使用密钥,这个设置可以在Keychain.app.

    (在某种程度上,它类似于带有键盘的硬件令牌,希望您输入 PIN 码,而无需与 Java 进行任何交互。)

  • 如果您的钥匙串中有多个身份(证书 + 相应的私钥),则存在一个错误,即KeychainStore无论如何只能看到一个。(上次我检查时,这还没有解决。)

  • Safari 在客户端证书选择方面存在许多问题(并不总是提供选择,您必须事先手动进行身份配置,或者只有在服务器拒绝没有客户端证书的连接时才会这样做:Apache HttpdSSLVerifyClient optional不会不行)。我不确定这些问题是否已得到解决。

  • 如果您使用的是自签名客户端证书,您应该配置 Tomcat 以将其宣传为接受的颁发者,或者它应该发送一个空列表。尽管后者由 TLS 1.1 明确授权,但我不确定 OSX 在客户端的行为方式。

于 2012-04-16T17:50:45.363 回答