Java开发网 Java开发网
注册 | 登录 | 帮助 | 搜索 | 排行榜 | 发帖统计  

您没有登录

» Java开发网 » Java Security » 精华区  

按打印兼容模式打印这个话题 打印话题    把这个话题寄给朋友 寄给朋友    该主题的所有更新都将Email到你的邮箱 订阅主题
flat modethreaded modego to previous topicgo to next topicgo to back
话题被移动
该话题已被移动 - menzy , 2004-11-22 16:25
如果您尚不清楚该话题被移动的原因,请参考论坛规则以及本版公告或者联系本版版主。
作者 如何获取服务商Https的内容 [精华]
donyjp



发贴: 0
积分: 0
于 2004-11-16 12:51 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
已经从服务商得到P12文件,并在IE中能正常通过Https检索服务商的网页。
现在想用Java获取Https的内容进行相应处理,始终不能成功,望高手指点,
在下先行谢过了。我的处理过程如下。

方法一:

keytool -export -storepass password -storetype PKCS12 -keystore ????.p12 -file test.cer -alias aaaaa
keytool -import -storepass password -alias aaaaa -keystore truststore -file test.cer
java URLReader

出错信息:No trusted certificate found

方法二:

openssl pkcs12 -cacerts -nokeys -in ????.p12 -out ca-certs.pem
openssl x509 -in ca-certs.pem -outform pem -out ca-certs.cer
keytool -import -storepass password -alias aaaaa -keystore truststore -file ca-certs.cer
java URLReader
出错信息:Received fatal alert: handshake_failure
比方法一走的要远些,至少找到了trusted certificate ,只是最后握手失败。

-------------------------------------------------
URLReader.java 比较简单, 如下:

import java.net.*;
import java.io.*;

public class URLReader {
public static void main(String[] args) throws Exception {

System.setProperty("javax.net.ssl.trustStore", "truststore");
System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
java.security.Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider() );

    URL url= new URL("https://???.???.??/sscgi/RefMsPos?MSTYPE=NODID");
    BufferedReader in =
new BufferedReader(  new InputStreamReader(url.openStream()));

  String inputLine;
   while ((inputLine = in.readLine()) != null)
   System.out.println(inputLine);
   in.close();
}
}



作者 Re:如何获取服务商Https的内容 [Re:donyjp]
floater

Java Jedi

总版主


发贴: 3233
积分: 421
于 2004-11-16 21:57 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
方法一 出错信息:No trusted certificate found: This means your truststore doesn't have the ca cert of the server's cert. I assume your test.cer is the client cert, ca-certs.pem is the ca cert for the server's cert. You need to import this ca cert into your truststore. One more thing is that you have to make sure your client side cert have the default password changeit(both in the alias and the keystore, this is a bug in jsse, otherwise it would fail).

方法二 is not necessary, the error is in the comment of the following code.

As for how to convert p12 to jks format(You have to convert client certs into this format), search here, I posted the code already.

This code is part of a small lib I built, so there is no sample code on how to use it, and thus you have to read through. I've used it in several projects already.

import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.HttpsURLConnection;

public class HttpsCertificate
{
public static final String TRUST_STORE = "javax.net.ssl.trustStore";
public static final String TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";
public static final String KEY_STORE = "javax.net.ssl.keyStore";
public static final String KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword";

private String _clientCertStoreFile = null;
private InputStream _clientCertInputStream = null;
private String _clientCertStorePswd = null;
private String _serverCertStoreFile = null;
private InputStream _serverCertInputStream = null;
private String _serverCertStorePswd = null;

private KeyManagerFactory _kmFactory;
private TrustManagerFactory _tmFactory;

private static boolean _debug = false;

/**
* If we just care server side cert, not client side cert.
* @param serverCertStoreFile String
* @param serverCertStorePswd String
*/
public HttpsCertificate(String serverCertStoreFile, String serverCertStorePswd)
{
_serverCertStoreFile = serverCertStoreFile;
_serverCertStorePswd = serverCertStorePswd;
}

public HttpsCertificate(InputStream serverCertInputStream, String serverCertStorePswd)
{
_serverCertInputStream = serverCertInputStream;
_serverCertStorePswd = serverCertStorePswd;
}

/**
* If we care both server side and client side certs.
* @param clientCertStoreFile String
* @param clientCertStorePswd String
* @param serverCertStoreFile String
* @param serverCertStorePswd String
*/
public HttpsCertificate(String clientCertStoreFile, String clientCertStorePswd,
String serverCertStoreFile, String serverCertStorePswd)
{
_clientCertStoreFile = clientCertStoreFile;
_clientCertStorePswd = clientCertStorePswd;
_serverCertStoreFile = serverCertStoreFile;
_serverCertStorePswd = serverCertStorePswd;
}

public HttpsCertificate(InputStream clientCertInputStream, String clientCertStorePswd,
InputStream serverCertInputStream, String serverCertStorePswd)
{
_clientCertInputStream = clientCertInputStream;
_clientCertStorePswd = clientCertStorePswd;
_serverCertInputStream = serverCertInputStream;
_serverCertStorePswd = serverCertStorePswd;
}

/**
* This version works for all stand-alone apps, not for web apps.
*/
public void setCertForStandAlone()
{
if (_clientCertStoreFile != null)
{
System.setProperty(TRUST_STORE, _clientCertStoreFile);
System.setProperty(TRUST_STORE_PASSWORD, _clientCertStorePswd);
}
if (_serverCertStoreFile != null)
{
System.setProperty(KEY_STORE, _serverCertStoreFile);
System.setProperty(KEY_STORE_PASSWORD, _serverCertStorePswd);
}
}

/**
* This version works for web apps.
*/
public void setCertForWebApps(Object httpConn)
{
setClientCert();
setServerCert();

try
{
// now create the context
SSLContext ctx = SSLContext.getInstance("SSL");

if (_kmFactory != null)
{
if (_tmFactory != null)
{
ctx.init(_kmFactory.getKeyManagers(), _tmFactory.getTrustManagers(), null);
}
else
{
ctx.init(_kmFactory.getKeyManagers(), null, null);
}
}
else
{
if (_tmFactory != null)
{
ctx.init(null, _tmFactory.getTrustManagers(), null);
}
else
{
return; // if both null, there is no need to set anything at all.
}
}

// without the following line, we would get the following error:
// in a web server, hit it the first time, we get this error:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
// but hit it again, it's fine. Looks like it didn't take what we set for the default.
// so we set it in this method.
// Furthermore, for backward compatibility, we have to check these,
// thanks to IBM and SUN for making this world more miserable!
System.out.println("httpConn Class=" + httpConn.getClass().getName());
if (httpConn.getClass().getName().equals("com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnection"))
{
com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnection httpsConn = (com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnection)httpConn;
httpsConn.setSSLSocketFactory(ctx.getSocketFactory());
httpsConn.setDefaultSSLSocketFactory(ctx.getSocketFactory());
}
else if (httpConn.getClass().getName().equals("com.ibm.net.ssl.internal.www.protocol.https.HttpsURLConnection"))
{
com.ibm.net.ssl.internal.www.protocol.https.HttpsURLConnection httpsConn = (com.ibm.net.ssl.internal.www.protocol.https.HttpsURLConnection)httpConn;
httpsConn.setSSLSocketFactory(ctx.getSocketFactory());
httpsConn.setDefaultSSLSocketFactory(ctx.getSocketFactory());
}
else // don't check here, so in worst case an error bombs out to alert users.
// Note: JDK1.4 and above will use this code block.
{
javax.net.ssl.HttpsURLConnection httpsConn = (javax.net.ssl.HttpsURLConnection)httpConn;
httpsConn.setSSLSocketFactory(ctx.getSocketFactory());
httpsConn.setDefaultSSLSocketFactory(ctx.getSocketFactory());
}
}
catch (NoSuchAlgorithmException nsae)
{
nsae.printStackTrace();
throw new HttpException("error in loading SSL context");
}
catch (KeyManagementException kme)
{
kme.printStackTrace();
throw new HttpException("error on initializing SSL context");
}
}

private void setClientCert()
{
debug("set client side cert ...");
if (_clientCertStoreFile != null)
{
debug("read client side file ...");
_clientCertInputStream = getKeystoreInputStream(_clientCertStoreFile);
}

try
{
if (_clientCertInputStream != null)
{
debug("setting client side cert ...");
KeyStore clientCertKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
clientCertKeyStore.load(_clientCertInputStream, _clientCertStorePswd.toCharArray());
_kmFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
_kmFactory.init(clientCertKeyStore, _clientCertStorePswd.toCharArray());
}
else
{
debug("nothing to set for the client cert!");
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
throw new HttpException("can't load client certificate file");
}
catch (KeyStoreException kse)
{
kse.printStackTrace();
throw new HttpException("can't find keystore instance");
}
catch (NoSuchAlgorithmException nsae)
{
nsae.printStackTrace();
throw new HttpException("error in loading client cert");
}
catch (CertificateException ce)
{
ce.printStackTrace();
throw new HttpException("error in reading");
}
catch (UnrecoverableKeyException uke)
{
uke.printStackTrace();
throw new HttpException("error in initializing client cert");
}
}

private void setServerCert()
{
debug("set server side cert ...");
if (_serverCertStoreFile != null)
{
debug("read server side cert ...");
_serverCertInputStream = getKeystoreInputStream(_serverCertStoreFile);
}
if (_serverCertInputStream != null)
{
try
{
debug("setting server side cert ...");
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(_serverCertInputStream, _serverCertStorePswd.toCharArray());
_tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
_tmFactory.init(trustStore);
}
catch (IOException ioe)
{
ioe.printStackTrace();
throw new HttpException("can't load server certificate file");
}
catch (KeyStoreException kse)
{
kse.printStackTrace();
throw new HttpException("can't find server cert keystore instance");
}
catch (NoSuchAlgorithmException nsae)
{
nsae.printStackTrace();
throw new HttpException("error in loading server cert");
}
catch (CertificateException ce)
{
ce.printStackTrace();
throw new HttpException("error in reading server cert");
}
}
else
{
debug("Nothing to set for the server cert");
}
}

private InputStream getKeystoreInputStream(String fileName)
{
InputStream retInputStream = null;

if (fileName == null) return retInputStream;

try
{
retInputStream = new FileInputStream(fileName);
return retInputStream;
}
catch (FileNotFoundException fnfe)
{
System.out.println("info: failed to get file: " + fileName + " through filesystem: " + fnfe.getMessage());
System.out.println("Note: this is just info, not necessarily a fault! Will try with classpath loading.");
retInputStream = this.getClass().getResourceAsStream(fileName);
}

//retInputStream = HTTPSMessage.class.getResourceAsStream(fileName);
//retInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
debug("The input stream is: " + retInputStream);
return retInputStream;
}

private static void debug(String s)
{
if (_debug == true && s != null) System.out.println("HttpsCertificate: - " + s);
}
}



"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
- Martin Fowler, Refactoring - Improving the Design of Existing Code
作者 Re:如何获取服务商Https的内容 [Re:donyjp]
donyjp



发贴: 0
积分: 0
于 2004-11-17 09:31 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
谢谢你的回复!

按照你所说的,对方法1进行了改进,但仍然出现HandShake failure:

del *.cer
del *.pem
del truststore

echo CL-CERT
openssl pkcs12 -clcerts -nokeys -in my.p12 -out cl-certs.pem
openssl x509 -in cl-certs.pem -outform pem -out cl-certs.cer
keytool -import -storepass changeit -alias changeit -keystore truststore -file cl-certs.cer

echo CA-CERT
openssl pkcs12 -cacerts -nokeys -in my.p12 -out ca-certs.pem
openssl x509 -in ca-certs.pem -outform pem -out ca-certs.cer
keytool  -import -storepass changeit  -alias ca-certs -keystore truststore -file ca-certs.cer

Java URLReader

err info:
------------------------------------------------------------
...
main, WRITE: TLSv1 Change Cipher Spec, length = 1
JsseJCE: Using JSSE internal implementation for cipher RC4
*** Finished
verify_data: { 7, 82, 0, 89, 67, 34, 218, 245, 229, 140, 249, 40 }
***
main, WRITE: TLSv1 Handshake, length = 32
waiting for close_notify or alert: state 1
Exception while waiting for close java.net.SocketException: Software caused conn
ection abort: recv failed
main, handling exception: java.net.SocketException: Software caused connection a
bort: recv failed
main, SEND TLSv1 ALERT: fatal, description = unexpected_message
main, WRITE: TLSv1 Alert, length = 18
Exception sending alert: java.net.SocketException: Software caused connection ab
ort: socket write error
main, called closeSocket()
Exception in thread "main" java.net.SocketException: Software caused connection
abort: recv failed
...


donyjp edited on 2004-11-17 09:50

作者 Re:如何获取服务商Https的内容 [Re:donyjp]
floater

Java Jedi

总版主


发贴: 3233
积分: 421
于 2004-11-17 09:58 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
for client cert, you have to use jks format, openssl doesn't work, you can't combine them either.


"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
- Martin Fowler, Refactoring - Improving the Design of Existing Code
作者 Re:如何获取服务商Https的内容 [Re:donyjp]
donyjp



发贴: 0
积分: 0
于 2004-11-17 10:27 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Would you like to get me a correct bat to do so simple work.
Thank a lot.



作者 Re:如何获取服务商Https的内容 [Re:donyjp]
donyjp



发贴: 0
积分: 0
于 2004-11-17 10:43 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
使用你的 PKCS12ToJKS 转换p12到jks, 得到 my.jks

del *.cer
del *.pem
del truststore

echo CL-CERTS
keytool -export -storepass 243794C6 -keystore my.jks -file cl-certs.cer -alias n001a000000473
keytool -import -storepass changeit -alias changeit -keystore truststore -file cl-certs.cer

echo CA-CERTS
openssl pkcs12 -cacerts -nokeys -in my.p12 -out ca-certs.pem
openssl x509 -in ca-certs.pem -outform pem -out ca-certs.cer
keytool -import -storepass changeit -alias ca-certs -keystore truststore -file ca-certs.cer

Java URLReader

仍然出同样错误。



作者 Re:如何获取服务商Https的内容 [Re:donyjp]
floater

Java Jedi

总版主


发贴: 3233
积分: 421
于 2004-11-19 00:31 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
I don't use batch files at all. But here is the process:

export your client cert from IE, when prompt to type in password, type in "changeit"(without quote).
now use the java code to convert it from p12/pfx to jks.
use keytool to check the passwords for this jks file and the entry for your cert inside this keystore/jks(there should be only one entry). Make sure both passwords are changeit, if not, change them using keytool.
Now the client side is done.

Now you need to get the ca cert for server side cert. One way is to go to that site and click the lock icon in the status bar of IE, go to cert path tab and click on the ca cert(s), they should be in your browsers already, write down the names so you can find them in the cert store in IE. Export them and import them to a truststore.

Now you can use the jks and the truststore with the code above.

From your code, I assume you are using jdk1.3(There are two lines that gives the hint).

I don't use openssl at all since I am on xp.

I've been doing this for the last 3 years, it's been working for me all the time.

Good luck.



"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
- Martin Fowler, Refactoring - Improving the Design of Existing Code
作者 Re:如何获取服务商Https的内容 [Re:donyjp]
donyjp



发贴: 0
积分: 0
于 2004-11-19 11:48 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
谢谢你的回复,多有打扰了!

我无法从IE中导出client cert, 只能导出RootCA。
另外运行Java程序并没有使用JKS文件,是否Java程序不对?



作者 Re:如何获取服务商Https的内容 [Re:donyjp]
floater

Java Jedi

总版主


发贴: 3233
积分: 421
于 2004-11-19 23:25 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Since you have the p12 client cert already, just import into IE and then export it again. The reason you need to do this is you need to control the password of the client cert. When you import into IE, there is a checkbox you have to check(I think it's related to exportable). When you export, set the password to changeit.

When you use the above java code, you need to supply the .jks file name, jsse uses jks format underneathe. Otherwise, you will get errors.



"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
- Martin Fowler, Refactoring - Improving the Design of Existing Code

flat modethreaded modego to previous topicgo to next topicgo to back
  已读帖子
  新的帖子
  被删除的帖子
Jump to the top of page

   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923