点击打开链接http://my.oschina.net/blackylin/blog/144136
项目中Android https或http请求地址重定向为HTTPS的地址,相信很多人都遇到了这个异常(无终端认证):
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
因为HTTPS:超文本安全传输协议,和HTTP相比,多了一个SSL/TSL的认证过程,端口为443
第一种处理方式:添加个继承SSLSocketFactory的
自定义类。并在初始化httpclient支持https时,注册进去。
public class HttpClientHelper {
private static HttpClient httpClient;
private HttpClientHelper() {
}
public static synchronized HttpClient getHttpClient() {
if (null == httpClient) {
// 初始化工作
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //允许所有主机的验证
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params,
HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
// 设置连接管理器的超时
ConnManagerParams.setTimeout(params, 10000);
// 设置连接超时
HttpConnectionParams.setConnectionTimeout(params, 10000);
// 设置socket超时
HttpConnectionParams.setSoTimeout(params, 10000);
// 设置http https支持
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schReg.register(new Scheme("https", sf, 443));
ClientConnectionManager conManager = new ThreadSafeClientConnManager(
params, schReg);
httpClient = new DefaultHttpClient(conManager, params);
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
return httpClient;
}
}
class SSLSocketFactoryEx extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryEx(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port,
autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
又找到了一种解决方案,其过程大致这样的:
1.浏览器访问https地址,保存提示的证书到本地,放到android项目中的assets目录。
2.导入证书,代码如下。
3.把证书添加为信任。
String requestHTTPSPage(String mUrl) {
InputStream ins = null;
String result = "";
try {
ins = context.getAssets().open("app_pay.cer"); //下载的证书放到项目中的assets目录中
CertificateFactory cerFactory = CertificateFactory
.getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(ins);
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", cer);
SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);
Scheme sch = new Scheme("https", socketFactory, 443);
HttpClient mHttpClient = new DefaultHttpClient();
mHttpClient.getConnectionManager().getSchemeRegistry()
.register(sch);
BufferedReader reader = null;
try {
Log.d(TAG, "executeGet is in,murl:" + mUrl);
HttpGet request = new HttpGet();
request.setURI(new URI(mUrl));
HttpResponse response = mHttpClient.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
request.abort();
return result;
}
reader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
Log.d(TAG, "mUrl=" + mUrl + "\nresult = " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
// TODO: handle exception
} finally {
try {
if (ins != null)
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}