我僅在2.3.x設備上(可能有些)收到此錯誤。它適用於運行Android版本以上的任何其他設備。Android 2.3.x javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到認證路徑的信任錨點
這裏是我的HTTPRequestController:
public class HttpRequestController {
private final static String TAG = "HttpRequestController";
private static HttpRequestController instance;
public enum Method {
PUT, POST, DELETE, GET
}
private HttpRequestController() {
}
public static HttpRequestController getInstance() {
if (instance == null)
instance = new HttpRequestController();
return instance;
}
public String doRequest(String url, HashMap<Object, Object> data,
Method method, String token) throws Exception {
InputStream certificateInputStream = null;
if (MyApplication.PRODUCTION) {
certificateInputStream = MyApplication.context
.getResources().openRawResource(R.raw.production_cert);
LogUtils.log("using production SSL certificate");
} else {
certificateInputStream = MyApplication.context
.getResources().openRawResource(R.raw.staging_cert);
LogUtils.log("using staging SSL certificate");
}
KeyStore trustStore = KeyStore.getInstance("BKS");
try{
trustStore.load(certificateInputStream,
"re3d6Exe5HBsdskad8efj8CxZwv".toCharArray());
} finally {
certificateInputStream.close();
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
LogUtils.log("SSL: did init TrustManagerFactory with trust keyStore");
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
LogUtils.log("SSL: did init context with trust keyStore");
URL request = new URL(url);
HttpsURLConnection urlConnection = (HttpsURLConnection) request
.openConnection();
LogUtils.log("SSL: did open HttpsURLConnection");
urlConnection.setHostnameVerifier(new StrictHostnameVerifier());
urlConnection.setSSLSocketFactory(context.getSocketFactory());
urlConnection.setConnectTimeout(15000);
LogUtils.log("SSL: did set Factory and Timeout.");
if (method != Method.GET){
urlConnection.setDoOutput(true);
}
urlConnection.setDoInput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
LogUtils.log("SSL: urlConnection did set request properties.");
if (token != null) {
urlConnection.setRequestProperty("Authorization", "Token " + token);
}
urlConnection.setRequestMethod(method.toString());
urlConnection.connect();
LogUtils.log("SSL: urlConnection did connect.");
if (method != Method.GET) {
ObjectMapper mapper = new ObjectMapper();
String jsonValue = mapper.writeValueAsString(data);
OutputStream os = urlConnection.getOutputStream();
os.write(jsonValue.getBytes());
os.flush();
LogUtils.log(TAG, "Params: " + jsonValue);
}
LogUtils.log(TAG, method.toString() + ": " + url);
InputStream in = null;
if (urlConnection.getResponseCode() == 200) {
in = urlConnection.getInputStream();
} else {
in = urlConnection.getErrorStream();
}
String response = convertStreamToString(in);
LogUtils.log(TAG, "Got response : " + url);
LogUtils.log(TAG, "Response : " + response);
return response;
}
public String convertStreamToString(InputStream inputStream) {
BufferedReader buffReader = new BufferedReader(new InputStreamReader(
inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
try {
while ((line = buffReader.readLine()) != null) {
stringBuilder.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
}
public HttpClient retrieveHttpClient() {
return new MyHttpClient(MyApplication.context);
}
}
當我運行命令:
openssl s_client -debug -connect www.mysitedomain.com:443
我得到的迴應:
--
some key stuff
--
Certificate chain
0 s:/OU=Domain Control Validated/CN=www.mydomainname.com
i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - G2
1 s:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - G2
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
some more certificate stuff
-----END CERTIFICATE-----
ubject=/OU=Domain Control Validated/CN=www.mydomainname.com
issuer=/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Domain Validation CA - G2
---
No client certificate CA names sent
---
SSL handshake has read 4091 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 57C379C59483809A7FE1BF8E235C5BFA7789E62AAEBCA9BC14B5273F5D1304E7
Session-ID-ctx:
Master-Key: 6FCD498D1294415A42B57420F0C05AB903EF8E56CB6F1530390F73AF5E4CBC22B359D5CDA09811E075A5C598002C380D
Key-Arg : None
Start Time: 1390473282
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
所以返回好嗎...但它仍然給我爲我測試的2.3.x設備發生這個錯誤。
我這點後得到一個異常:
LogUtils.log("SSL: urlConnection did set request properties.");
這裏是個例外:
01-23 10:20:28.459: W/System.err(1623): javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:477)
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328)
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.setupSecureSocket(HttpConnection.java:185)
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:433)
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeConnection(HttpsURLConnectionImpl.java:378)
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:205)
01-23 10:20:28.459: W/System.err(1623): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:152)
我打電話,這是這裏的方式:
String response = HttpRequestController
.getInstance()
.doRequest(ApiUrls.LOGIN, params, Method.POST, null);
它適用於任何其他運行2.3.x以上Android版本的設備(從我測試過的)。
Android文檔似乎沒有寫入關於2.3兼容性的主題。
我用同樣的代碼,以谷歌文檔,但它說 '/load-der.crt:打開失敗:ENOENT(沒有這樣的文件或目錄)' – Naz141
Naz141,你需要在您的項目中包含了您想要接受的證書(在本例中爲文件「load-der.crt」)。您可以加載它,例如從資產文件夾。 – zapotec