有很多关于这个问题的帖子(javax.net.ssl.SSLPeerUnverifiedException:没有对等证书)但是我找不到任何适合我的帖子。
许多帖子(如this和this)通过允许接受所有证书来“解决”这个问题,当然,除了测试之外,这不是一个好的解决方案。
其他人似乎非常本地化,对我不起作用。我真的希望有人有一些我缺乏的见解。
所以,我的问题:我正在测试只能通过本地网络访问的服务器,通过HTTPS连接。我需要通过浏览器拨打电话工作正常。没有抱怨证书,如果你检查证书,一切看起来都不错。
当我试用我的Android设备时,我得到javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
以下是调用它的代码:
StringBuilder builder = new StringBuilder();
builder.append( /* stuff goes here*/ );
httpGet.setEntity(new UrlEncodedFormEntity(nameValuePairs));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
// Execute HTTP Post Request. Response body returned as a string
HttpClient httpClient = MyActivity.getHttpClient();
HttpGet httpGet = new HttpGet(builder.toString());
String jsonResponse = httpClient.execute(httpGet, responseHandler); //Line causing the Exception
我的MyActivity.getHttpClient()
代码:
protected synchronized static HttpClient getHttpClient(){
if (httpClient != null)
return httpClient;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, TIMEOUT_CONNECTION);
HttpConnectionParams.setSoTimeout(httpParameters, TIMEOUT_SOCKET);
HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
//Thread safe in case various AsyncTasks try to access it concurrently
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager cm = new ThreadSafeClientConnManager(httpParameters, schemeRegistry);
httpClient = new DefaultHttpClient(cm, httpParameters);
CookieStore cookieStore = httpClient.getCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
return httpClient;
}
非常感谢任何帮助。
修改
另外,我只是提到了其他应用的其他SSL问题,但之前添加了SchemeRegistry
部分为我修复了它。
修改2
到目前为止,我只在Android 3.1上测试过,但无论如何我都需要在Android 2.2+上运行。我刚刚在我的Android选项卡(Android 3.1)上的浏览器上进行了测试,并且它抱怨了证书。它在我的电脑浏览器上很好,但不适用于Android浏览器或我的应用程序。
编辑3
原来iOS浏览器也抱怨它。我开始认为这是这里描述的证书链问题(SSL certificate is not trusted - on mobile only)
答案 0 :(得分:19)
事实证明我的代码很好,问题是服务器没有返回完整的证书链。有关更多信息,请参阅此SO帖子和此超级用户帖子:
SSL certificate is not trusted - on mobile only
https://superuser.com/questions/347588/how-do-ssl-chains-work
答案 1 :(得分:5)
尝试以下代码: -
BasicHttpResponse httpResponse = null;
HttpPost httppost = new HttpPost(URL);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is
// established.
int timeoutConnection = ConstantLib.CONNECTION_TIMEOUT;
HttpConnectionParams.setConnectionTimeout(httpParameters,
timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = ConstantLib.CONNECTION_TIMEOUT;
HttpConnectionParams
.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(
httpParameters);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair(ConstantLib.locale,
locale));
答案 2 :(得分:5)
在我的情况下,一切都工作得很好。 2天后,我的设备突然没有显示任何https站点或图像链接。
经过一番调查后发现我的时间设置在设备上不是最新的。
我正确地更改了时间设置并且运行正常。
答案 3 :(得分:-1)
我使用自签名证书+ IP地址时遇到此异常。只需添加这些行
$successful_login = false;
$query = 'SELECT password FROM user WHERE UserID = ?';
$stmt = mysqli_prepare($con, $query);
$stmt->bind_param('s', $userid);
$stmt->bind_result($row_passwd);
$stmt->execute();
if ($stmt->fetch()) {
$successful_login = password_verify($password, $row_passwd);
}
if ($successful_login) {
echo 'Account validated.';
}
你的HttpURLConnection会起作用。 这个技巧与CA的验证无关!因此,如果我指定错误的CA并使用该技巧,我将得到另一个例外。所以主持人仍然值得信赖
以防万一,我将在此处留下用于指定您自己的CA的代码:
HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
不要忘记使用很酷的功能buildTypes并将不同的CA放在res文件夹中进行调试/发布。