android - 客户端证书未随 soap 调用一起发送

标签 android ssl client-certificates

我想出了以下代码来使用客户端/服务器证书身份验证调用 Web 服务,但服务器从未获得客户端证书,这里出了什么问题?

package com.cs;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Collection;
import java.util.Iterator;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import net.my.myHostnameVerifier;
import net.my.myX509TrustManager;
import android.app.Activity;
import android.os.Bundle;

public class ClientServerActivity extends Activity {
    protected static int debug = 1;
    String soapRequest="";
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        soapRequest = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:nam=\"https://ind-etsdev/namespace\">"
                + "<soapenv:Header/>"
                + "<soapenv:Body>"
                + "<nam:CreateSession>"
                + "<DeviceID>something</DeviceID>"
                + "<UserName>something</UserName>"
                + "<UserPassword>something</UserPassword>"
                + "</nam:CreateSession>"
                + "</soapenv:Body>"
                + "</soapenv:Envelope>";
        runService();
    }
    private void runService(){
        try {
            debug = 1;
            String certPassword = "my1234";
            initializeURLConn(certPassword, "BKS", null);
            String urlStr = "https://webserviceurl";
            int requestStatus = -1;
            requestStatus = doHttpRequest(urlStr);
            System.out.println("Request Status: " + requestStatus);
        }
        catch(Throwable x) {
            x.printStackTrace();
        }
    }
    private int doHttpRequest(String urlStr) throws Exception {
        String responseBody = "";

        //Open the HTTP connection
        URL url = new URL(urlStr);
        HttpsURLConnection urlconnection = (HttpsURLConnection)url.openConnection();
        urlconnection.setHostnameVerifier(new myHostnameVerifier(true, debug));
        urlconnection.setDoOutput(true);
        urlconnection.setDoInput(true);
        urlconnection.setRequestProperty("Content-Type", "text/xml;charset=UTF-8"); 

        urlconnection.setRequestProperty("Content-Length", Integer.toString(soapRequest.length())); 
        urlconnection.setRequestProperty("SOAPAction", "https://soapaction"); 

        urlconnection.setUseCaches(false);
        urlconnection.setConnectTimeout(30000); //30 seconds
        urlconnection.setReadTimeout(180000); //3 minutes
        urlconnection.connect();

        // Send Request to the server 
        try {
            DataOutputStream outStr = new DataOutputStream(urlconnection.getOutputStream ());   
            outStr.writeBytes(soapRequest); 
            outStr.flush(); 
            outStr.close();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } 

        //Read the response
        int responseCode = urlconnection.getResponseCode();

        InputStreamReader responseISR = null;
        BufferedReader responseBR = null;

        try {
            responseISR = new InputStreamReader(urlconnection.getInputStream());
        }
        catch (IOException e) {
            System.out.println("IOException!!!!");
            e.printStackTrace();
            responseISR = new InputStreamReader(urlconnection.getErrorStream());
        }

        responseBR = new BufferedReader(responseISR);
        StringBuffer stringbuffer = new StringBuffer();
        String responseLine;
        while ((responseLine = responseBR.readLine()) != null) {
            stringbuffer.append(responseLine + "\n");
        }
        responseBR.close();
        urlconnection.disconnect();

        responseBody = stringbuffer.toString();

        System.out.println(responseBody);

        return responseCode;
    }


    private void initializeURLConn(String keystorePassword, String keystoreType, String trustFileName) throws Exception {
        // Create keystore
        KeyStore keystore = KeyStore.getInstance(keystoreType);
        InputStream keystoreFIS = getResources().openRawResource(R.raw.clientvik);
        keystore.load(keystoreFIS, keystorePassword != null ? keystorePassword.toCharArray(): null);

        // Create key manager
        KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmfactory.init(keystore, keystorePassword != null ? keystorePassword.toCharArray(): null);
        KeyManager[] keymanagers = kmfactory.getKeyManagers();

        TrustManager[] trustmanagers = null;
        if (trustFileName == null) {
            // Create a trust manager that does not validate certificate chains
            trustmanagers = new TrustManager[]{new myX509TrustManager()};
        }
        else {
            // Create trust keystore
            KeyStore ksCA = java.security.KeyStore.getInstance("JKS");
            ksCA.load(null, null);

            // Add MRTU cert to the keystore as a trusted certificate
            FileInputStream truststoreFIS = new FileInputStream(trustFileName);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Collection c = cf.generateCertificates(truststoreFIS);
            Iterator i = c.iterator();
            while (i.hasNext()) {
                Certificate cert = (Certificate)i.next();
                //System.out.println(cert);
                ksCA.setCertificateEntry("trustedCA", cert);
            }

            // Create trust manager
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
            tmf.init(ksCA);
            trustmanagers = (TrustManager[])tmf.getTrustManagers();
        }

        // Install the key manager and trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(keymanagers, trustmanagers, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

}

最佳答案

我发现了问题所在。我的客户端证书中没有包含完整证书链 的证书。我创建了具有完整证书链的 bks keystore 并且它有效。

关于android - 客户端证书未随 soap 调用一起发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9839019/

相关文章:

php - Royal Mail Shipping API - SOAP 连接和 pem/证书查询

c# - 如何从 Bouncy CaSTLe 创建 X509 证书以用于 AuthenticateAsServer?

带 SSL 的 Tomcat,网站部分的客户端/服务器身份验证

python-3.x - Python 证书验证失败 : unable to get local issuer certificate

android - 如何在 Android 应用程序中管理 Google Play 服务更新?

android - 如何避免为每个属性键入 "android"?

android - 动画重置文本大小后的TextView

IIS 6 在同一站点上为通配符证书绑定(bind)多个 ssl

ssl - 在应用程序级别的 WAS 中通过 HTTPS 配置 JAX-WS Web 服务

android - 我的 Android 应用程序在按下主页按钮后崩溃