gpt4 book ai didi

java - 使用自签名证书 : hostName not verified 的 Android Https 连接

转载 作者:太空宇宙 更新时间:2023-11-03 13:41:31 27 4
gpt4 key购买 nike

您好,我正在使用证书测试 Android 连接。我在我的 ubuntu 桌面上创建了一个默认的 ssl 服务器。启用 ssl 并创建默认的自签名证书。然后我用 firefox 连接到 https://localhost,将证书添加到异常(exception),然后我使用 Firefox 将证书保存为 .pem 文件。我在 res/raw 中将 certificate.pem 添加到我的 android projetc

我已经从 android 开发者网站获得了这段代码,可以使用我的证书通过 https 进行连接(我不想相信一切,我只想使用原始文件夹中的证书验证证书是否正确)。

所以当我连接时,我得到:java.lang.RuntimeException: java.io.IOException: 主机名 '192.168.1.111' 未验证

这是我用来验证证书的类

public class VerifyKey extends AsyncTask<Void, Void, Void>{

public static final String CERTIFICATE_TYPE_X_509 = "X.509";
public static final String CERTIFICATE_ALIAS = "user_desktop";
public static final String SERVER_URL = "https://192.168.1.111";
@Override
protected Void doInBackground(Void... params) {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = null;
InputStream certificateInputStream = getApplicationContext().getResources().openRawResource(R.raw.user_desktop);
Certificate certificate = null;
try {
cf = CertificateFactory.getInstance(CERTIFICATE_TYPE_X_509);
certificate = cf.generateCertificate(certificateInputStream);
Log.d(TAG, "Certificate : " + certificate.toString());
Log.d(TAG, "Certificate public key : " + certificate.getPublicKey());
} catch (CertificateException e) {
throw new RuntimeException(e);
} finally {
if (certificateInputStream != null) {
try {
certificateInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance(keyStoreType);
if (keyStore != null) {
keyStore.load(null, null);
keyStore.setCertificateEntry(CERTIFICATE_ALIAS, certificate);
} else {
throw new RuntimeException("KeyStore is null");
}
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = null;
try {
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
if (tmf != null) {
tmf.init(keyStore);
} else {
throw new RuntimeException("TrustManagerFactory is null");
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
}

// Create an SSLContext that uses our TrustManager
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");

TrustManager[] trustManagers = tmf.getTrustManagers();
sslContext.init(null, trustManagers, null);

} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
}

// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = null;
HttpsURLConnection httpsURLConnection =
null;
InputStream in = null;
try {
url = new URL(SERVER_URL);
Log.d(TAG, "URL : "+url.toString());
httpsURLConnection = (HttpsURLConnection)url.openConnection();
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Log.d(TAG, "Socket factory : "+socketFactory.toString());
httpsURLConnection.setSSLSocketFactory(socketFactory);

in = httpsURLConnection.getInputStream(); //IOException exception gets triggered here

Toast.makeText(getApplicationContext(), in.toString(), Toast.LENGTH_SHORT).show();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (SSLHandshakeException e){
throw new RuntimeException(e);
} catch(UnknownHostException e){
throw new RuntimeException(e);
} catch (ConnectException e1){
throw new RuntimeException(e1);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
}

我从 http://developer.android.com/training/articles/security-ssl.html#SelfSigned 得到了这段代码

我在 Android 4.3 的 Samsung Galaxy s4 上遇到这个错误

我对 HTTPS 没有太多经验,所以在这里我想实现的是为应用程序提供证书,这将允许验证服务器证书。如果有人可以建议我可以在代码中修改什么。

我也有疑问,因为我的服务器是 .local 服务器,但我使用 ip 连接,目标是能够同时使用 ip 和主机名进行连接,在验证主机名时会不会有问题?提前致谢

编辑:我添加了获取主机名的代码:

InetAddress addr = InetAddress.getByName(SERVER_URL);
String hostName = addr.getHostName();

我已经尝试使用主机名而不是 ip,但我仍然遇到相同的异常:

Caused by: java.io.IOException: Hostname '<user.hostname.com>' was not verified
at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446)
at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

最佳答案

我设法解决了问题,实际上是证书的问题:

sudo a2enmod ssl
sudo rm -rf /etc/apache2/ssl
sudo mkdir /etc/apache2/ssl
sudo openssl req -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.key

将/etc/apache2/ssl/apache.pem 复制到其他地方,将它的权限更改为 777 (???)然后将新的 apache.pem 添加到应用程序的 res/raw 文件夹中

然后在通用名称字段中设置了服务器的 FQDN,例如 host.name.com,然后更新了/etc/apache2/sites-available/default-ssl 中的证书和 key 设置

这一切都归功于网站 https://library.linode.com/web-servers/apache/ssl-guides/ubuntu-10.04-lucid

关于java - 使用自签名证书 : hostName not verified 的 Android Https 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20270070/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com