Java – how to use httpsurlconnection certificate authentication?

I am trying to connect to an HTTPS URL, but I need to use client authentication and a certificate placed on my system by third-party software

I have no idea how I should find or use it. All I have to do is c# sample code, which is very different from all the Java answers I have found (for example, does keystore need some kind of password?)

This is the c# sample code I have

System.Security.Cryptography.X509Certificates.X509CertificateCollection SSC_Certs = 
    new System.Security.Cryptography.X509Certificates.X509CertificateCollection();

Microsoft.Web.Services2.Security.X509.X509CertificateStore WS2_store =
    Microsoft.Web.Services2.Security.X509.X509CertificateStore.CurrentUserStore(
    Microsoft.Web.Services2.Security.X509.X509CertificateStore.MyStore);

WS2_store.OpenRead();

Microsoft.Web.Services2.Security.X509.X509CertificateCollection WS2_store_Certs = WS2_store.Certificates;

Then it just traverses WS2_ store_ Certificates certificatecollection and check in this way Further, it sets the following certificate:

HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url_string);
httpWebRequest.ClientCertificates = SSC_Certs;

All this seems quite logical. Even if I don't know how to find the certificate, I still can't find the Java equivalent

UPDATE

The connection I'm making is part of a larger application that relies on JDK 5, but I've managed to find the certificate I'm looking for using sunmscapi jar An error occurred when I tried to connect using the windows keystore, so I thought I got the certificate I needed from the windows store and inserted it into the default Java, so I thought of this problem Now I get an eofexception, followed by sslhandshakeexception, saying "the remote host closes the connection during the handshake." The SSL debug trace does not show an immediate problem because the certificate I need is displayed in the certificate chain

It completes the whole clientkeyexchange, and then the last message I get from the debug log is

[write] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C D3 E1 E7 3D   C2 37 2F 41 F9 38 26 CC  .......=.7/A.8&.
Padded plaintext before ENCRYPTION:  len = 32
0000: 14 00 00 0C D3 E1 E7 3D   C2 37 2F 41 F9 38 26 CC  .......=.7/A.8&.
0010: CB 10 05 A1 3D C3 13 1C   EC 39 ED 93 79 9E 4D B0  ....=....9..y.M.
AWT-EventQueue-1,WRITE: TLSv1 Handshake,length = 32
[Raw write]: length = 37
0000: 16 03 01 00 20 06 B1 D8   8F 9B 70 92 F4 AD 0D 91  .... .....p.....
0010: 25 9C 7D 3E 65 C1 8C A7   F7 DA 09 C0 84 FF F4 4A  %..>e..........J
0020: CE FD 4D 65 8D                                     ..Me.
AWT-EventQueue-1,received EOFException: error

And I'm using the code to establish the connection

KeyStore jks = KeyStore.getInstance(KeyStore.getDefaultType());
jks.load(null,null);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
jks.setCertificateEntry("alias",cert1); //X509Certificate obtained from windows keystore
kmf.init(jks,new char[0]);

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(),new TrustManager[]{tm},null);

sslsocketfactory = sslContext.getSocketFactory();
System.setProperty("https.proxyHost",proxyurl);
System.setProperty("https.proxyPort",proxyport);

Authenticator.setDefault(new MyAuthenticator("proxyID","proxyPassword"));
URL url = new URL(null,urlStr,new sun.net.www.protocol.https.Handler());
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();
uc.setSSLSocketFactory(sslsocketfactory);
uc.setAllowUserInteraction(true);
uc.setRequestMethod("POST");
uc.connect();

(I haven't tried httpclient yet because I don't know how to find the certificate file, and I don't know if it's the same on every client system)

Another update

I found the CAS of the certificates I needed in the windows-root keystore (and used. Verify() to check whether they were checked out). I also added them to the Java keystore, but there was still no change I think they should enter the truststore, but I haven't found a way to program (I don't want to rely on end users to do such things, because I can guarantee that certificates and CAS will exist due to the third-party software mentioned at the beginning of this ridiculous and long problem)

More updates

In addition to the previous updates, I conclude that my problem must be that my CA is not in the cacerts file of Java, so it obtains the list of trusted CAS from the server, but it cannot recognize them. Subsequently, it will not send a single certificate, resulting in connection failure So the question remains, how can Java use the keystore as a truststore or programmatically add certificates to cacerts (without requiring a file path)? Because if that's not possible, just let me secretly choose C, voodoo I'll stab a Duke doll with a needle just in case

Solution

OK, so the title of your question is how to use certificate authentication and httpsurlconnection? I have an example of work In order to work, it has one prerequisite:

>You must have a keystore with your certificate file (I know your situation does not fully allow this, but please wait a moment so that we can narrow down your question a little, because it is too complex to answer directly.)

So, put your hand on the actual certificate file first If you are on Windows 7, you can do this by following these steps:

>Open Internet Explorer, > open the tool (which is the cog icon in Internet Explorer 9), > click Internet Options, > go to the content tab, > Click certificate to find the certificate at hand, > click it and click export and save it to a file (Der encoded binary X.509)

(after export, delete it from other certificates to ensure that Java will not use it in any way. I don't know whether I can use it, but it won't be hurt)

Now you must create a key store file and import the exported certificate into it, which can be done in the following ways

> keytool -importcert -file <certificate> -keystore <keystore> -alias <alias>

(obviously, keytool must be on your way to work. It is a part of JDK.)

It will prompt you to enter the password (the password of the key store, without any operation on the certificate). I don't know how to set it to "" now, so set it to password or other

After that, you can establish a secure connection to your endpoint through the proxy through the following steps

>First, load the key store file

InputStream trustStream = new FileInputStream("path/to/<keystore>");
char[] trustPassword = "<password>".tocharArray();

>Initialize keystore

KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStream,trustPassword);

>Initializes the trustmanager object (I think these solutions for handling certificates or something like that, but as far as I'm concerned, it's magic.)

TrustManagerFactory trustFactory =
    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
TrustManager[] trustManagers = trustFactory.getTrustManagers();

>Create a new sslcontext, load the trustmanager object into it, and set it to the default value Note that because sslcontext Getdefault () returns an instance of a class that cannot be modified (or more like the default instance), which is why we must use sslcontext getInstance(“SSL” ). In addition, don't forget to set the new sslcontext to the default value, because without this code, it will become poof

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null,trustManagers,null);
SSLContext.setDefault(sslContext);

>Create a proxy and set up authentication for it (instead of using system. Setproperty (...) use the proxy class. Oh, don't be used by type HTTP (misleading)

Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("<host>",<port>));

>Set up authentication for your proxy (I have used a free proxy, which does not require authentication, so I can't test this part of the problem now.)

Authenticator.setDefault(new Authenticator() {

  @Override
  protected PasswordAuthentication getpasswordAuthentication() {
    return new PasswordAuthentication("<user>","<password>".tocharArray());
  }
});

Connect to your destination by passing the previously created proxy to the connection (I have used the URL of one of my company's services, which requires a certificate - of course, I entered the certificate in my own key store.)

URL url = new URL("<endpoint>");
URLConnection connection = url.openConnection(proxy);
connection.connect();

If it doesn't work like this (you get the error), then try with httpsurlconnection

HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
   httpsConnection.setAllowUserInteraction(true);
   httpsConnection.setRequestMethod("POST");

Basically, if the server (the location of the resource pointed to by the URL connected to) requires credentials, setallowuserinteraction will start, right? Now, I can't test it, but I see that if you can let the baby use a server that doesn't need authentication to access its resources, you're good, because the server will ask you to verify yourself only after you establish a connection

If you still receive some errors after these, please post them

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>