我一直在努力让这个工作。我正在尝试使用自签名证书通过 https 连接到我的服务器。我不认为现在还没有任何页面或示例。
我做了什么:
它使用openssl s_client -connect domain.com:443
从服务器获取证书。然后使用充气城堡创建一个bks密钥库。
从原始文件夹中读取创建的密钥库,将其添加到sslfactory,然后再添加到OkHttpClient。像这样:
public ApiService() {
mClient = new OkHttpClient();
mClient.setConnectTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
mClient.setReadTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
mClient.setCache(getCache());
mClient.setCertificatePinner(getPinnedCerts());
mClient.setSslSocketFactory(getSSL());
}
protected SSLSocketFactory getSSL() {
try {
KeyStore trusted = KeyStore.getInstance("BKS");
InputStream in = Beadict.getAppContext().getResources().openRawResource(R.raw.mytruststore);
trusted.load(in, "pwd".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trusted);
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext.getSocketFactory();
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
public CertificatePinner getPinnedCerts() {
return new CertificatePinner.Builder()
.add("domain.com", "sha1/theSha=")
.build();
}
由于某种原因,这始终会生成带有或不带密钥库的SSLPeerUnverifiedException
。有或没有CertificatePinner
。
javax.net.ssl.SSLPeerUnverifiedException: Hostname domain.com not verified: 0
W/System.err﹕ certificate: sha1/theSha=
W/System.err﹕ DN: 1.2.840.113549.1.9.1=#1610696e666f40626561646963742e636f6d,CN=http://domain.com,OU=development,O=domain,L=Valencia,ST=Valencia,C=ES
W/System.err﹕ subjectAltNames: []
W/System.err﹕ at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:124)
W/System.err﹕ at com.squareup.okhttp.Connection.connect(Connection.java:143)
W/System.err﹕ at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185)
W/System.err﹕ at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)
W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
W/System.err﹕ at com.squareup.okhttp.Call.getResponse(Call.java:273)
W/System.err﹕ at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:230)
W/System.err﹕ at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:201)
W/System.err﹕ at com.squareup.okhttp.Call.execute(Call.java:81)
...
我做错了什么?
答案 0 :(得分:21)
我遇到了同样的问题,但我需要我的应用程序才能在多个临时环境中工作,所有这些环境都有自签名证书。更糟糕的是,他们可以随时更改这些证书。
要解决此问题,仅在连接到分段时,我添加了一个信任所有证书的SSLSocketFactory。这修复了java错误,但它给我留下了此票证中提到的okhttp异常。
为了避免这个错误,我需要再向okHttpClient添加一个自定义。这为我解决了错误。
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
答案 1 :(得分:10)
将setHostNameVerifier
设置为okHttpBuilder
即可解决此问题。确保验证方法应该返回true。
样品:
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient client = builder.build();
答案 2 :(得分:2)
请检查客户端证书上的CN名称是否已添加到“主题”备用名称中。我有同样的问题
答案 3 :(得分:1)
在生成证书的过程中,如果uri是一个IP,则必须设置subjectAltName
才能通过验证。
“在某些情况下,URI被指定为IP地址而不是主机名。在这种情况下,iPAddress subjectAltName必须存在于证书中,并且必须与URI中的IP完全匹配。” RFC(由巴斯在评论中提及)
不要通过HostnameVerifier
来烦恼客户端,而是通过以下方式重新使用自签名证书(我们已对其进行控制):
openssl req \
-newkey rsa:2048 \
-nodes \
-x509 \
-days 36500 -nodes \
-addext "subjectAltName = IP.1:1.2.3.4" \
-keyout /etc/ssl/private/nginx-selfsigned2.key \
-out /etc/ssl/certs/nginx-selfsigned2.crt
插件,如果在Android上也需要信任证书:
the crt is pem format and can be imported into android via
<?xml version="1.0" encoding="utf-8"?>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="@raw/nginx_selfsigned2" />
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
因此,我们验证证书来自受信任的源,并且以前通过主机名验证(通过SAN)来确保与之通信的服务器为他的ip提供正确的证书。
更多信息:https://developer.android.com/training/articles/security-config https://developer.android.com/training/articles/security-ssl.html#SelfSigned
答案 4 :(得分:0)
如果您在
body {
background-color:#2a303d;
text-align: center;
font-family: 'Ubuntu', sans-serif;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
#rock {
width: 80%;
position: absolute;
top: 45.8%;
left: 39.75%;
transform: translate(-50%, -50%);
transform: rotate(360deg);
height: 100px;
width: 100px
}
#paper {
width: 80%;
position: absolute;
top: 45.8%;
left: 46.75%;
transform: translate(-50%, -50%);
transform: rotate(360deg);
height: 100px;
width: 100px;
}
#scissors {
width: 80%;
position: absolute;
top: 52.05%;
left: 57.25%;
transform: translate(-50%, -50%);
height: 100px;
width: 100px;
}
#RPS {
font-size: 65px;
margin-top: 40px;
}
#botPick {
font-size: 50px;
margin-top: 350px;
}
#Score p {
margin:0;
padding:0;
margin-left: 5px;
font-size: 36px;
display: inline-block;
line-height: 80px;
vertical-align: top;
}
#winOrLose {
color: white;
}
中使用 network_security_config
解决res/xml
并且您更改了域/IP 地址,请记住您应该将 Cleartext HTTP traffic not permitted
值更改为新地址。
这对我有用。
includeSubdomains