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

2022-09-02 12:58:04

问题

我想将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());
}

例外。

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.err(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.execute(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:487) 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:487) 03-02 16:58: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:487) 03-02 16:58: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:487) 03-02 16:58:25.250: W/System.err(1868): at org.apache.http.impl.client.abstractHttpClient.execute(AbstractHttpClient摘要HttpClient.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:1868): 1) 03-02 16:58:25.250: W/System.err(1868): at 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 android.os.ATasync$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 settings。

<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>

答案 1

最后,我解决了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代码中,我编写了以下代码来读取该密钥库.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();

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

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

引用


答案 2

请求方法不适合 URL 。这就是我们所知道的。POST/

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

/* ... */
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
/* ... */

示例 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());
/* ... */