当前位置: 首页 > 面试题库 >

Android:使用HttpsURLConnection的HTTPS(SSL)连接

牛昱
2023-03-14
问题内容

我有2个应用程序,一个是Servlet / Tomcat服务器,另一个是Android应用程序。

我想使用HttpURLConnection在两者之间发送和接收XML。

码:

    private String sendPostRequest(String requeststring) {

    DataInputStream dis = null;
    StringBuffer messagebuffer = new StringBuffer();

    HttpURLConnection urlConnection = null;

    try {
        URL url = new URL(this.getServerURL());

        urlConnection = (HttpURLConnection) url.openConnection();

        urlConnection.setDoOutput(true);

        urlConnection.setRequestMethod("POST");

        OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());

        out.write(requeststring.getBytes());

        out.flush();

        InputStream in = new BufferedInputStream(urlConnection.getInputStream());

        dis = new DataInputStream(in);

        int ch;

        long len = urlConnection.getContentLength();

        if (len != -1) {

            for (int i = 0; i < len; i++)

                if ((ch = dis.read()) != -1) {

                    messagebuffer.append((char) ch);
                }
        } else {

            while ((ch = dis.read()) != -1)
                messagebuffer.append((char) ch);
        }

        dis.close();

    } catch (Exception e) {

        e.printStackTrace();

    } finally {

        urlConnection.disconnect();
    }

    return messagebuffer.toString();
}

现在,我需要使用SSL来发送XML以确保安全。

首先,我使用Java Keytool生成.keystore文件。

Keytool  -keygen -alias tomcat -keyalg RSA

然后我将XML代码放在Tomcat的server.xml文件中以使用SSL

<Connector 
port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="c:/Documents and Settings/MyUser/.keystore"
keystorePass="password"
clientAuth="false" sslProtocol="TLS" 
/>

然后,将其更改为HttpsURLConnection的HttpURLConnection

    private String sendPostRequest(String requeststring) {

    DataInputStream dis = null;
    StringBuffer messagebuffer = new StringBuffer();

    HttpURLConnection urlConnection = null;

    //Conexion por HTTPS
    HttpsURLConnection urlHttpsConnection = null;

    try {
        URL url = new URL(this.getServerURL());

        //urlConnection = (HttpURLConnection) url.openConnection();

        //Si necesito usar HTTPS
        if (url.getProtocol().toLowerCase().equals("https")) {

            trustAllHosts();

            //Creo la Conexion
            urlHttpsConnection = (HttpsURLConnection) url.openConnection();

            //Seteo la verificacion para que NO verifique nada!!
            urlHttpsConnection.setHostnameVerifier(DO_NOT_VERIFY);

            //Asigno a la otra variable para usar simpre la mism
            urlConnection = urlHttpsConnection;

        } else {

            urlConnection = (HttpURLConnection) url.openConnection();
        }

//Do the same like up

并添加trustAllHosts方法以信任每个服务器(不要检查任何证书)

private static void trustAllHosts() {

    X509TrustManager easyTrustManager = new X509TrustManager() {

        public void checkClientTrusted(
                X509Certificate[] chain,
                String authType) throws CertificateException {
            // Oh, I am easy!
        }

        public void checkServerTrusted(
                X509Certificate[] chain,
                String authType) throws CertificateException {
            // Oh, I am easy!
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

    };

    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager};

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");

        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    } catch (Exception e) {
            e.printStackTrace();
    }
}

这些更改效果很好,但是我不想信任每台服务器。我想使用我的密钥库文件来验证连接并以正确的方式使用SSL。我在互联网上阅读了很多书,做了很多测试,但是我不明白我必须做些什么以及如何做。

有人可以帮我吗?

非常感谢你

对不起,我英语不好

-------------------------更新2011/08/24 -------------------

好吧,我还在努力。我做了一个新方法来设置KeyStore,InputStream等

该方法如下所示:

private static void trustIFNetServer() {

    try {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        KeyStore ks = KeyStore.getInstance("BKS");

        InputStream in = context.getResources().openRawResource(R.raw.mykeystore);

        String keyPassword = "password";

        ks.load(in, keyPassword.toCharArray());

        in.close();

        tmf.init(ks);

        TrustManager[] tms = tmf.getTrustManagers();

        SSLContext sc = SSLContext.getInstance("TLS");

    sc.init(null, tms, new java.security.SecureRandom());

    } catch (Exception e) {
    e.printStackTrace();
    }
}

首先,我在密钥和证书方面遇到很多问题,但现在可以正常工作了(我认为是这样)

我现在的问题是超时异常。我不知道为什么会生成。我认为这与数据写入有关,但是我还无法解决。

任何想法?


问题答案:

您需要按照此处所述为自签名证书创建信任存储文件。在客户端使用它来连接服务器。不管您使用JKS还是其他格式都没有关系,我现在假设使用JKS。

要实现您的想法TrustManager,显然需要一个不同的方法。您可以将TrustManagerFactory其信任设置与新创建的信任存储区一起使用。

TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream in = new FileInputStream("<path to your key store>");
ks.load(in, "password".toCharArray());
in.close();
tmf.init(ks);
TrustManager[] tms = tmf.getTrustManagers();

使用tms来初始化你SSLContext,而不是为新的信任设置用于您的SSL / TLS连接。

你还应该确保该CN服务器TLS证书的一部分,等于您的服务器,如的FQDN(完全合格的域名),如果你的服务器基本URL是“
https://www.example.com ”,那么CN的证书应为“
www.example.com”。主机名验证需要此功能,此功能可防止中间人攻击。您可以禁用此功能,但只有在使用此功能时,您的连接才会真正安全。



 类似资料:
  • 我得到一个"异常在线程"主"javax.net.ssl.SSLHandshake异常:收到致命警报:handshake_failure"下面的代码。有人知道如何修复它吗?

  • 问题内容: 我正在做一个https帖子,但是却得到ssl异常的一个例外,不受信任的服务器证书。如果我做正常的HTTP,它工作正常。我是否必须以某种方式接受服务器证书? 问题答案: 我正在猜测,但是如果你想进行实际的握手,则必须让android知道你的证书。如果你只想接受任何内容,请使用以下伪代码通过Apache HTTP Client获得所需的内容: CustomSSLSocketFactory:

  • 我的连接代码如下所示: 干杯,马尔辛

  • 我试图使用PowerShell从https网站抓取html内容。 不幸的是,该站点只例外一组有限的SSL/TLS密码套件,不支持Powershell可用的套件。 如果尝试使用Invoke-WebRequest cmdlet,我会收到以下错误消息: 调用-网络请求:请求被中止:无法创建SSL/TLS安全通道。 问题: 是否有办法指定PowerShell使用的客户端SSL/TLS密码套件? 还有其他c

  • 我有一个问题,当我尝试读取任何输入时,我的网络连接会抛出一个EOFException。该代码适用于某些网络调用,但不适用于其他网络调用。如果我尝试从连接中读取任何内容,则会失败并出现上述错误。 例: 以下是每个堆栈的跟踪: getResponse: 缓冲输入流: 感谢您的任何帮助, 瑞克 编辑 我找到了我的答案: 这不是一个有据可查的答案。它出现在一些较新版本的android中,存在一个带有回收u

  • 我在Java中与SSL连接有问题。 我使用java 1.7.80和S. O.: ubuntu 14.04 我的问题是证书,甚至证书。我有四个必须使用pkcs12格式连接的元素。 -- -- -- -- 1) 步骤-将文件cer转换为文件pem 2)步骤-创建链证书的联合pem文件 3)步骤-创建p12文件 好啊我的第一个测试是在浏览器(Mozilla Firefox)中导入p12文件以验证操作。导