Android 上的自签名 SSL 接受
如何在 Android 上接受 Java 自签名证书?
代码示例将是完美的。
我在互联网上到处查找,虽然有些人声称找到了解决方案,但它要么不起作用,要么没有示例代码来支持它。
How do I accept a self-signed certificate in Java on Android?
A code sample would be perfect.
I've looked everywhere on the Internet and while some people claim to have found the solution, it either does not work or there is no sample code to back it up.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我在 ExchangeIt 中具有此功能,它通过 WebDav 连接到 Microsoft Exchange。 以下是创建 HttpClient 的一些代码,它将通过 SSL 连接到自签名证书:
EasySSLSocketFactory 是 此处,EasyX509TrustManager 为 此处。
ExchangeIt 的代码是开源的,托管在 googlecode 此处,如果您有任何问题。 我不再积极致力于它,但代码应该可以工作。
请注意,自 Android 2.2 以来,该过程发生了一些变化,因此请检查 this 使上面的代码工作。
I have this functionality in exchangeIt, which connects to Microsoft exchange via WebDav. Here's some code to create an HttpClient which will connect to self signed cert's via SSL:
The EasySSLSocketFactory is here, and the EasyX509TrustManager is here.
The code for exchangeIt is open source, and hosted on googlecode here, if you have any issues. I'm not actively working on it anymore, but the code should work.
Note that since Android 2.2 the process has changed a bit, so check this to make the code above work.
我昨天在将我们公司的 RESTful API 迁移到 HTTPS 时遇到了这个问题,但使用的是自签名 SSL 证书。
我到处寻找,但我发现的所有“正确”标记答案都包括禁用证书验证,显然覆盖了 SSL 的所有含义。
我终于找到了解决方案:
创建本地密钥库
要使您的应用能够验证自签名证书,您需要以 Android 可以信任您的端点的方式提供带有证书的自定义密钥库。
此类自定义密钥库的格式是来自 BouncyCastle 的“BKS”,因此您需要可以下载的 1.46 版本的 BouncyCastleProvider 此处。
您还需要自签名证书,我假设它名为
self_cert.pem
。现在创建密钥库的命令是:
PATH_TO_KEYSTORE
指向将在其中创建密钥库的文件。 它一定不存在。PATH_TO_bcprov-jdk15on-146.jar.JAR
是下载的 .jar 库的路径。STOREPASS
是您新创建的密钥库密码。将新创建的密钥库从
PATH_TO_KEYSTORE
复制到res/raw/certs.bks
(certs.bks 只是文件名;您可以使用任何您想要的名称)在
res/values/strings.xml
中创建一个键创建一个继承
的类DefaultHttpClient
现在只需使用
**MyHttpClient**
的实例即可使用**DefaultHttpClient**
进行 HTTPS 查询,它将正确使用和验证您的自签名 SSL 证书。I faced this issue yesterday, while migrating our company's RESTful API to HTTPS, but using self-signed SSL certificates.
I've looking everywhere, but all the "correct" marked answers I've found consisted of disabling certificate validation, clearly overriding all the sense of SSL.
I finally came to a solution:
Create Local KeyStore
To enable your app to validate your self-signed certificates, you need to provide a custom keystore with the certificates in a manner that Android can trust your endpoint.
The format for such custom keystores is "BKS" from BouncyCastle, so you need the 1.46 version of BouncyCastleProvider that you can download here.
You also need your self-signed certificate, I will assume it's named
self_cert.pem
.Now the command for creating your keystore is:
PATH_TO_KEYSTORE
points to a file where your keystore will be created. It MUST NOT EXIST.PATH_TO_bcprov-jdk15on-146.jar.JAR
is the path to the downloaded .jar libary.STOREPASS
is your newly created keystore password.Copy your newly created keystore from
PATH_TO_KEYSTORE
tores/raw/certs.bks
(certs.bks is just the file name; you can use whatever name you wish)Create a key in
res/values/strings.xml
withCreate a this class that inherits
DefaultHttpClient
Now simply use an instance of
**MyHttpClient**
as you would with**DefaultHttpClient**
to make your HTTPS queries, and it will use and validate correctly your self-signed SSL certificates.正如 EJP 正确评论的那样,“读者应该注意到这种技术根本不安全。除非至少有一个对等点经过身份验证,否则 SSL 并不安全。请参阅 RFC 2246。”
话虽如此,这里还有另一种方法,无需任何验证额外课程:
As EJP correctly commented, "Readers should note that this technique is radically insecure. SSL is not secure unless at least one peer is authenticated. See RFC 2246."
Having said that, here's another way, without any extra classes:
除非我错过了什么,否则本页上的其他答案都是危险的,并且在功能上相当于根本不使用 SSL。 如果您信任自签名证书而不进行进一步检查以确保证书是您期望的证书,那么任何人都可以创建自签名证书并可以冒充您的服务器。 到那时,你就没有真正的安全感了。
执行此操作的唯一合法方法(无需编写完整的 SSL 堆栈)是在证书验证过程中添加一个额外的受信任锚点以供信任。 两者都涉及将受信任的锚点证书硬编码到您的应用程序中,并将其添加到操作系统提供的任何受信任的锚点(否则,如果您获得真正的证书,您将无法连接到您的站点)。
我知道有两种方法可以实现此目的:
按照 http://www.ibm.com/developerworks/java/library/j-customssl/#8
创建 X509TrustManager 的自定义实例并重写 getAcceptedIssuers 方法以返回包含您的证书的数组:
请注意,此代码完全未经测试,甚至可能无法编译,但至少应该引导您正确的方向方向。
Unless I missed something, the other answers on this page are DANGEROUS, and are functionally equivalent to not using SSL at all. If you trust self-signed certificates without doing further checks to make sure the certificates are the ones that you are expecting, then anyone can create a self-signed certificate and can pretend to be your server. At that point, you have no real security.
The only legitimate way to do this (without writing a full SSL stack) is to add an additional trusted anchor to be trusted during the certificate verification process. Both involve hard-coding the trusted anchor certificate into your app and adding it to whatever trusted anchors that the OS provides (or else you won't be able to connect to your site if you get a real certificate).
I'm aware of two ways to do this:
Create a custom trust store as described at http://www.ibm.com/developerworks/java/library/j-customssl/#8
Create a custom instance of X509TrustManager and override the getAcceptedIssuers method to return an array that contains your certificate:
Note that this code is completely untested and may not even compile, but should at least steer you in the right direction.
如果您按如下方式修改更大的 createSocket 方法重载,Brian Yarger 的答案也适用于 Android 2.2。 我花了一段时间才让自签名 SSL 正常工作。
Brian Yarger's answer works in Android 2.2 as well if you modify the bigger createSocket method overload as follows. It took me a while to get self-signed SSLs working.
在 Android 上,
HttpProtocolParams
接受ProtocolVersion
而不是HttpVersion
。On Android,
HttpProtocolParams
acceptsProtocolVersion
rather thanHttpVersion
.@Chris - 将此作为答案发布,因为我还无法添加评论。 我想知道您的方法在使用 webView 时是否应该有效。 我无法在 Android 2.3 上这样做 - 相反,我只是得到一个白屏。
经过更多搜索后,我发现了这个 用于处理 webView 中的 SSL 错误的简单修复,这对我来说就像一个魅力。
在处理程序中,我检查是否处于特殊的开发模式并调用 handler.proceed(),否则调用 handler.cancel()。 这使我可以根据本地网站上的自签名证书进行开发。
@Chris - Posting this as an answer since I can't add comments (yet). I'm wondering if your approach is supposed to work when using a webView. I can't get it do so on Android 2.3 - instead I just get a white screen.
After some more searching, I came across this simple fix for handling SSL errors in a webView which worked like a charm for me.
In the handler I check to see if I'm in a special dev mode and call handler.proceed(), otherwise I call handler.cancel(). This allows me to do development against a self-signed cert on a local website.
这个用例有很多替代方案。 如果您不想在代码库中包含任何自定义代码,例如自定义
TrustManager
我建议尝试 GitHub - SSLContext Kickstart 和以下代码片段:SSL 配置
HttpClient 配置
HttpsUrlConnection
There are a-lot alternatives for this use case. If you don't want to have any custom code in your code base such as custom
TrustManager
I would suggest to try GitHub - SSLContext Kickstart and the following code snippet:SSL configuration
HttpClient configuration
HttpsUrlConnection