在带有weblogic服务器的java客户端中使用pkcs12证书进行相互身份验证

时间:2014-05-07 12:21:44

标签: authentication ssl weblogic pki

我无法通过Java客户端使用PKCS12 ssl证书从Weblogic服务器获取mbeans。

  • 服务器:Weblogic
  • 客户端:Java客户端/ JConsole

用于创建自签名证书的服务器端命令: 使用Weblogic CertGen实用程序,Weblogic CertGenCA.der和证书颁发机构创建证书。

java utils.CertGen -certfile ServerCert -keyfile ServerKey -keyfilepass keypass

java utils.der2pem CertGenCA.der

type serverCert.pem CertGenCA.pem >> myCert.pem

Server Keystore created>>
java utils.ImportPrivateKey -keystore  SeverIdentity.jks -storepass storepass -storetype JKS \
    -keypass keypass -alias mykey -certfile myCert.pem -keyfile ServerKey.pem \
    -keyfilepass keypass

Server Truststore used>>
DemoTrust.jks (Default Weblogic truststore)

用于创建PKCS12自签名证书的客户端命令:

java utils.CertGen -certfile ClientCert -keyfile ClientKey -keyfilepass keypass

openssl pkcs12 -export -in ClientCert.pem -inkey ClientKey.pem -out client-pkcs-12-cert

在Weblogic管理控制台中完成配置:

Keystores: Custom Identity Custom Trust.
Custom Identity Keystore:  D:\certificate\latest\pkcs\SeverIdentity.jks
Custom Identity Keystore Type: JKS
Custom Identity Keystore Passphrase: storepass (same as –storepass value of ImportPrivateKey)
Confirm Custom Identity Keystore Passphrase: storepass
Custom Trust Keystore: D:\certificate\latest\pkcs\DemoTrust.jks
Custom Trust Keystore Type: JKS
Custom Trust Keystore Passphrase: DemoTrustKeyStorePassPhrase
Custom Trust Keystore Passphrase: DemoTrustKeyStorePassPhrase

在setDomainEnv.cmd中完成的配置:

set JAVA_OPTIONS=%JAVA_OPTIONS% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9191 \
    -Dcom.sun.management.jmxremote.ssl=true -Dcom.sun.management.jmxremote.authenticate=false \
    -Djavax.net.ssl.keyStore=D:\certificate\latest\pkcs\SeverIdentity.jks \
    -Djavax.net.ssl.keyStorePassword=keypass -Djavax.net.ssl.trustStore=D:\certificate\latest\pkcs\DemoTrust.jks \
    -Djavax.net.ssl.trustStorePassword=DemoTrustKeyStorePassPhrase -Djava.rmi.server.hostname=10.112.69.200

参考:http://www.weblogic-tips.com/2010/05/20/two-way-ssl-on-weblogic-server/

Java客户端代码:

public static void main22(String args[]) {

try {

    System.setProperty("javax.net.ssl.keyStore",
            "D://certificate//latest//client-pkcs-12-cert");
    System.setProperty("javax.net.ssl.keyStorePassword", "keypass");

    HashMap<String, Object> env = new HashMap<String, Object>();
    String truststore = "D://certificate//latest//client-pkcs-12-cert";
    char truststorepass[] = "keypass".toCharArray();
    KeyStore ks = KeyStore.getInstance("pkcs12");
    ks.load(new FileInputStream(truststore), truststorepass);

    TrustManagerFactory tmf = TrustManagerFactory
            .getInstance("SunX509");

    tmf.init(ks);
    SSLContext ctx = SSLContext.getInstance("TLSv1");
    ctx.init(null, tmf.getTrustManagers(), null);
    SSLSocketFactory ssf = ctx.getSocketFactory();

    env.put("jmx.remote.tls.socket.factory", ssf);

    JMXServiceURL address = new JMXServiceURL("rmi", "", 0,
            "/jndi/rmi://localhost:9191/jmxrmi");

    JMXConnector jmxc = JMXConnectorFactory.connect(address, env);
    MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
    Set<ObjectInstance> beans = mbsc.queryMBeans(null, null);

    for (ObjectInstance instance : beans) {
        MBeanInfo info = mbsc.getMBeanInfo(instance.getObjectName());
        System.out.println(info);
    }

    jmxc.close();
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error :" + e.getMessage());
    }
}

我可以在使用JKS证书时获取mbeans但是当我使用PKCS12证书时,它在通过JMXConnectorFactory连接时出现以下错误: 行异常:JMXConnector jmxc = JMXConnectorFactory.connect(address,env);

例外:

java.rmi.ConnectIOException: Exception creating connection to: 10.112.69.200; nested exception is: 
       java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:614)
       at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
       at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
       at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110)
       at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
       at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2327)
       at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:277)
       at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
       at test.Test.main(Test.java:68)
Caused by: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
       at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:179)
       at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:192)
       at javax.rmi.ssl.SslRMIClientSocketFactory.createSocket(SslRMIClientSocketFactory.java:105)
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
       ... 8 more
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
       at java.security.Provider$Service.newInstance(Provider.java:1245)
       at sun.security.jca.GetInstance.getInstance(GetInstance.java:220)
       at sun.security.jca.GetInstance.getInstance(GetInstance.java:147)
       at javax.net.ssl.SSLContext.getInstance(SSLContext.java:125)
       at javax.net.ssl.SSLContext.getDefault(SSLContext.java:68)
       at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:102)
       at javax.rmi.ssl.SslRMIClientSocketFactory.getDefaultClientSocketFactory(SslRMIClientSocketFactory.java:192)
       at javax.rmi.ssl.SslRMIClientSocketFactory.createSocket(SslRMIClientSocketFactory.java:102)
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
       at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
       at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
       at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
       at sun.rmi.transport.DGCImpl_Stub.dirty(Unknown Source)
       at sun.rmi.transport.DGCClient$EndpointEntry.makeDirtyCall(DGCClient.java:342)
       at sun.rmi.transport.DGCClient$EndpointEntry.registerRefs(DGCClient.java:285)
       at sun.rmi.transport.DGCClient.registerRefs(DGCClient.java:121)
       at sun.rmi.transport.ConnectionInputStream.registerRefs(ConnectionInputStream.java:80)
       at sun.rmi.transport.StreamRemoteCall.releaseInputStream(StreamRemoteCall.java:138)
       at sun.rmi.transport.StreamRemoteCall.done(StreamRemoteCall.java:292)
       at sun.rmi.server.UnicastRef.done(UnicastRef.java:431)
       at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
       at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:97)
       at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:185)
       at javax.naming.InitialContext.lookup(InitialContext.java:392)
       at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1886)
       at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1856)
       at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:255)
       ... 2 more
Caused by: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
       at sun.security.util.DerInputStream.getLength(DerInputStream.java:544)
       at sun.security.util.DerValue.init(DerValue.java:347)
       at sun.security.util.DerValue.<init>(DerValue.java:303)
       at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1200)
       at java.security.KeyStore.load(KeyStore.java:1185)
       at com.sun.net.ssl.internal.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(TrustManagerFactoryImpl.java:202)
       at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.getDefaultTrustManager(DefaultSSLContextImpl.java:70)
       at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.<init>(DefaultSSLContextImpl.java:40)
       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
       at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
       at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
       at java.lang.Class.newInstance0(Class.java:357)
       at java.lang.Class.newInstance(Class.java:310)
       at java.security.Provider$Service.newInstance(Provider.java:1221)
       ... 28 more
error :Exception creating connection to: 10.112.69.200; nested exception is: 
       java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)

1 个答案:

答案 0 :(得分:2)

首先,......(编辑:我意识到我误读了部分错误,我的第一点肯定至少部分不正确。)

快速搜索您的错误消息(java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.)指向this IBM support page,建议使用JKS密钥库而不是PKCS#12(在服务器端,您没有这样做)或者证书中有不正确的字符。

其次,即使修复了服务器证书问题,也无法使用此代码进行客户端证书身份验证。

String truststore = "D://certificate//latest//client-pkcs-12-cert";
char truststorepass[] = "keypass".toCharArray();
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream(truststore), truststorepass);

TrustManagerFactory tmf = TrustManagerFactory
        .getInstance("SunX509");

tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);

PKCS#12文件应包含您的客户端证书及其私钥。它旨在用作密钥库,而不是信任库。也就是说,虽然在这两种情况下都将实体称为密钥库,但您可以将其与密钥管理器一起使用,而不是信任管理器。

在这里,您正在使用PKCS#12文件初始化SSLContext的信任管理器。这是你应该初始化的关键经理。

此外,如果您的代码使用的是与Sun / Oracle / OpenJDK无关的JRE,则应该避免硬编码“SunX509”,而是使用TrustManagerFactory.getDefaultAlgorthim()代替(实施此阶段时KeyManagerFactory。)