接受Java证书 [英] Accepting certificates in Java

查看:55
本文介绍了接受Java证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在通过Java与HTTPS站点交互时遇到问题.每次程序运行时,我的程序都使用一个带有不受信任证书的URL.该程序必须在多个系统上运行.目前,我有以下内容:

I'm having problems interacting with an HTTPS site via Java. My program uses one URL with an untrusted certificate each time the program runs. This program has to run on more than one system. Currently, I have the following:

public class A{
    HostnameVerifier hv = new HostnameVerifier(){
        public boolean verify(String urlHostName, SSLSession session){
            return true;
        }       
    };

    HttpsURLConnection.setDefaultHostnameVerifier(hv);

    javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
    javax.net.ssl.TrustManager tm = new miTM();
    trustAllCerts[0] = tm;
    javax.net.ssl.SSLContext sc = null;
    try {
        sc = javax.net.ssl.SSLContext.getInstance("SSL");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    try {
        sc.init(null, trustAllCerts, null);
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
   javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager{

    public java.security.cert.X509Certificate[] getAcceptedIssuers(){
        return null;
    }

    public boolean isServerTrusted(java.security.cert.X509Certificate[] certs){
        return true;
        }

    public boolean isClientTrusted(java.security.cert.X509Certificate[] certs){
        return true;
    }

    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException{
        return;
    }

    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException{
        return;
        }
}

使用此代码,我可以执行以下操作:

With this code, I can perform the following just fine:

URL url = new URL(urlString);
URLConnection cnx = url.openConnection();
cnx.connect();

InputStream ins = cnx.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(ins));
String curline;
while( (curline = in.readLine()) != null ) {
     System.out.println(curline);
}

但是,我无法执行以下操作:

However, I cannot do the following:

httpClient = new HttpClient();
PostMethod postMethod = null;
int intResult = 0;
postMethod = new PostMethod(authURL);
Enumeration emParams = authParams.propertyNames();
while (emParams.hasMoreElements()) {
  String paramName = (String) emParams.nextElement();
  String paramValue = authParams.getProperty(paramName);
     postMethod.addParameter(paramName, paramValue);
}

intResult = httpClient.executeMethod(postMethod);
postMethod.releaseConnection();
ins.close();

执行executeMethod(postMethod)时,出现SSLHandshakeException,CertPathBuilderException等.

When executeMethod(postMethod) is executed, I get an SSLHandshakeException, CertPathBuilderException, and so on.

该如何解决?我正在考虑要么接受证书,要么只是绕过​​所有证书验证(因为该程序在专用网络内部运行).

What can I do to remedy this? I'm thinking of either accepting the certificate or just bypassing all certificate validation (as the program runs internally within a private network).

谢谢

推荐答案

您似乎正在使用Apache HttpClient3.如果确实是版本3,则需要构建自己的 Apache HttpClient 3 SSL指南.这里有一个示例.

It looks like you're using Apache HttpClient 3. If this is indeed version 3, you need to build your own SecureProtocolSocketFactory as explained in the Apache HttpClient 3 SSL guide. There is an example here.

对于Apache HttpClient 4,您应该能够将 SSLContext 传递给(HttpClient) SSLSocketFactory 的构造函数,如

For Apache HttpClient 4, you should be able to pass an SSLContext to the constructor to the (HttpClient) SSLSocketFactory, as described in the answers to this question (including notes regarding host name verification).

但是,一般而言,不要遵循这种方法.这样,您就可以完全禁用SSL/TLS连接的身份验证部分,从而使其容易受到MITM攻击.

您应按照此答案中的说明,将服务器证书显式导入客户的信任存储中.

You should explicitly import the server certificate in your client's trust store instead, as described in this answer.

我正在考虑要么接受证书,要么只是绕过​​所有证书证书验证(因为程序在内部运行专用网络).

I'm thinking of either accepting the certificate or just bypassing all certificate validation (as the program runs internally within a private network).

您的意思是,您只愿意在您的专用网络内使用SSL/TLS进行加密,因为您对信任它的用户的信任度不高,无法查看可能绕过其计算机的流量,但是您还假设这些用户将无法执行MITM攻击.这不太有意义.如果您对它们足够信任,则最好以明文形式发送数据.如果不这样做,则应正确实施SSL/TLS,包括身份验证步骤(证书和主机名验证).

What you're saying is that you're willing to use SSL/TLS for encryption only within your private network because you don't trust its users enough not to look at the traffic that may go around their machines, but you're also assuming that these users won't be able to perform a MITM attack. This doesn't quite make sense. If you trust them enough, you might as well send the data in clear. If you don't, then you should implement SSL/TLS properly, including the authentication steps (certificate and host name verification).

这篇关于接受Java证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆