android中的https(无对等证书)问题

Vik*_*yan 19 java https android httpclient

问题

我想将https请求发送到我自己的服务器站点https://10.2.20.20/fido/EzPay/login.php并从中获取响应,并将其保存为例如字符串.我在互联网上找到了一些示例代码,并尝试测试它们以解决我的问题,但它们没有帮助.下面我介绍一些我测试过的代码部分.


代码示例:

我试试这段代码,但我总是得到同样的例外"没有同行证书"为什么?

try
{
    HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

    DefaultHttpClient client = new DefaultHttpClient();

    SchemeRegistry registry = new SchemeRegistry();
    SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
    socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
    registry.register(new Scheme("https", socketFactory, 443));
    SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
    DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

    // Set verifier      
    HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

    // Example send http request
    final String url = "https://10.2.20.20/fido/EzPay/login.php";
    HttpPost httpPost = new HttpPost(url);
    HttpResponse response = httpClient.execute(httpPost);

    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    String line = "";
    while ((line = rd.readLine()) != null) {
        Log.i(DownloadImageTask.class.getName(), line);
    }

}
catch(IOException ex)
{
    Log.e(DownloadImageTask.class.getName(), ex.getMessage());
}
Run Code Online (Sandbox Code Playgroud)

例外.

03-02 16:58:25.234:W/System.err(1868):javax.net.ssl.SSLPeerUnverifiedException:No peer certificate 03-02 16:58:25.238:W/System.err(1868):at org. apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:137)03-02 16:58:25.238:W/System.err(1868):at org.apache.http.conn.ssl.AbstractVerifier .verify(AbstractVerifier.java:93)03-02 16:58:25.238:W/System.err(1868):at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)03- 02 16:58:25.238:W/System.err(1868):at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)03-02 16:58:25.250:W/System.错误(1868):at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)03-02 16:58:25.250:W/System.err(1868):at org.apache.http .impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)03-02 16:58:25.250:W/System.err(1868):at org.apache.http.impl.client.DefaultRequestDirector.execut e(DefaultRequestDirector.java:360)03-02 16:58:25.250:W/System.err(1868):at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)03-02 16:58:25.250:W/System.err(1868):at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)03-02 16:58:25.250:W/System.err (1868):at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)03-02 16:58:25.250:W/System.err(1868):at com.https.test. DownloadImageTask.doInBackground(Https_testActivity.java:78)03-02 16:58:25.250:W/System.err(1868):at com.https.test.DownloadImageTask.doInBackground(Https_testActivity.java:1)03-02 16: 58:25.250:W/System.err(1868):在android.os.AsyncTask $ 2.call(AsyncTask.java:264)03-02 16:58:25.253:W/System.err(1868):at java. util.concurrent.FutureTask $ Sync.innerRun(FutureTask.java:305)03-02 16:58:25.253:W/System.err(1868):at java.util.concurrent.FutureTask.run(FutureTask.java:137 )03-02 16:58:25.253:W/System.err(1868):at和 roid.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:208)03-02 16:58:25.257:W/System.err(1868):at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1076)03-02 16:58:25.257:W/System.err(1868):at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:569)03-02 16:58:25.257:W/System.err(1868):at java.lang.Thread.run(Thread.java:856)


我做错了什么以及如何解决这个问题.为什么我得到" 无对等证书 "例外?

谢谢.

编辑


Windows Server设置.

<VirtualHost *:443>
  ServerName 10.2.20.20

 Alias /fido/EzPay/ "d:/fido/EzPay/" 
Alias /fido/EzPay "d:/fido/EzPay/" 

<Directory "d:/fido/EzPay/">
    Options Indexes FollowSymLinks MultiViews
    AllowOverride all
        Order allow,deny
    Allow from all
</Directory>


  # These are the actual SSL directives needed to get it all working!
  SSLEngine on
  SSLCertificateFile C:/wamp/bin/apache/apache2.2.17/conf/ssl/fidoserver.crt
  SSLCertificateKeyFile C:/wamp/bin/apache/apache2.2.17/conf/ssl/fidoserver.pem
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

Vik*_*yan 20

最后我解决了https问题.我在战斗时主要问题是在服务器中,具体在证书中.Android仅支持"BKS"证书,这就是我们无法从服务器获得响应的原因.为了解决这个问题,我阅读了30多篇文章,最后找到了解决方案.

我为解决这个问题所做的步骤你可以在下面看到:

我做的第一件事就是从我们的fidoserver.crt证书生成.bks密钥库文件,为了做到这一点,我已经阅读了这篇文章并做了以下事情:

  1. 打开cmd
  2. 转到JDK文件夹"cd X:\ Programs\Java\Jdk6\bin"
  3. 调用以下命令:

keytool -import -alias tomcat -file X://KeyStore/fidoserver.crt -keypass password - keystore X://KeyStore/keystore.bks -storetype BKS -storepass 222222 -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath X://KeyStore/bcprov-jdk16-146.jar

在运行此命令之前,我已下载Bouncy Castle .jar文件并将其放入带有证书的文件夹中.完成所有步骤后,我获得了keystore.bks文件,这是Android应用程序的正确证书文件.我把这个文件放在Androids mnc/sdcard文件夹中.在java代码中,我编写了以下代码来读取该keystore.bbk文件

KeyStore trustStore  = KeyStore.getInstance( "BKS" /*KeyStore.getDefaultType()*/ );
FileInputStream instream = new FileInputStream(new File("/mnt/sdcard/keystore.bks"));
try {
    trustStore.load(instream, "222222".toCharArray());
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch (CertificateException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try { instream.close(); } catch (Exception ignore) {}
}

// Create socket factory with given keystore.
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);

SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", socketFactory, 443);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);

HttpGet httpget = new HttpGet("https://10.2.20.20/fido/EzPay/login.php");

System.out.println("executing request " + httpget.getRequestLine());

HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();

System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
    System.out.println("Response content length:  " + entity.getContentLength());
}

// Print html.
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = in.readLine()) != null) {
     System.out.println(line);
}
in.close();
Run Code Online (Sandbox Code Playgroud)

这都允许m使用给定密码222222(我们在使用keytool创建密钥库时提供的密码)加载我们的证书.

在此之后,我的所有测试应用程序开始正常工作.现在我可以向https发送请求并从中获取响应.我用FIDO服务器测试了应用程序,一切都很棒!我想周一我将对EzPay应用程序进行一些更改,它将开始使用https连接.

参考


Can*_*ner 7

请求方法POST不适用于URL /.我们知道的就这些.

示例1不起作用,因为似乎您不允许POST向该页面发送请求.尝试:

/* ... */
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
/* ... */
Run Code Online (Sandbox Code Playgroud)

示例2不起作用,因为您不接受网站证书作为接受的证书,因此它也应该是这样的:

/* ... */
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
/* ... */
Run Code Online (Sandbox Code Playgroud)