连接到我的本地XAMPP托管网站时,SSL库中出现Android故障
我对任何与网络相关的编程都是新手,所以我知道我正在深入研究,但我在android HttpsURLConnection和本地XAMPP托管网站之间成功地进行SSL握手时遇到了问题,而不仅仅是一个返回Hello World的php脚本!首先,我可以从我的计算机(主机)和android手机的浏览器(https)加载此页面 问题: 当我尝试通过HttpsURLConnection将应用程序与服务器连接时,我遇到以下错误:连接到我的本地XAMPP托管网站时,SSL库中出现Android故障,android,apache,ssl,https,xampp,Android,Apache,Ssl,Https,Xampp,我对任何与网络相关的编程都是新手,所以我知道我正在深入研究,但我在android HttpsURLConnection和本地XAMPP托管网站之间成功地进行SSL握手时遇到了问题,而不仅仅是一个返回Hello World的php脚本!首先,我可以从我的计算机(主机)和android手机的浏览器(https)加载此页面 问题: 当我尝试通过HttpsURLConnection将应用程序与服务器连接时,我遇到以下错误: System.err﹕ javax.net.ssl.SSLHandshakeEx
System.err﹕ javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5e522ba8: Failure in SSL library, usually a protocol error
System.err﹕ error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5e5967e8:0x00000000)
System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:449)
System.err﹕ at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
System.err﹕ at com.android.okhttp.Connection.connect(Connection.java:107)
System.err﹕ at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
System.err﹕ at com.android.okhttp.internal.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:161)
System.err﹕ at yellowgames.battlenetfriendfinder.ServerConnection$TaskExecuter.doInBackground(ServerConnection.java:118)
System.err﹕ at yellowgames.battlenetfriendfinder.ServerConnection$TaskExecuter.doInBackground(ServerConnection.java:94)
System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:288)
System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237)
System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
System.err﹕ at java.lang.Thread.run(Thread.java:841)
System.err﹕ Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5e522ba8: Failure in SSL library, usually a protocol error
System.err﹕ error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5e5967e8:0x00000000)
System.err﹕ at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:406)
System.err﹕ ... 16 more
我的代码:
我的代码基于以下内容:
服务器端:
我生成了以下证书:
自从我的本地电脑和安卓浏览器可以访问它以来,这似乎起到了作用。此外,在XAMPP的ssl_request.log中,我可以从本地计算机或android浏览器看到所有连接尝试,但它甚至一次都没有提到来自应用程序的请求。这与access.log相同
我正在安卓4.4.2上测试安卓应用程序
我的实际问题
有人知道如何修复SSL握手错误吗?任何提示都是有用的!我尝试了很多在谷歌上可以找到的东西,但到目前为止都没有成功。安卓4.4.2版本上有一个已知的bug,这是使用TLSv1.x协议访问HTTPS时引起的。由于不支持TLS,握手失败,因此HttpsURLConnection退回到SSLv3协议,导致握手时发生错误。我还没有找到不涉及重新实现HttpsURLConnection的TrustManager以防止错误或不安全连接的解决方案 这就是我所做的: 将自定义信任管理器提供给SSLContext:
// Trust manager that recognizes you acceptance criteria, that being ignoring handshake errors
ResourceTrustManager trustManager = new ResourceTrustManager(sslKeyStores);
TrustManager[] trustManagers = {trustManager};
// use: org.apache.http.conn.ssl.AllowAllHostnameVerifier, this can be optional depending on your case.
AllowAllHostnameVerifier resourceHostNameVerifier = new AllowAllHostnameVerifier();
// Install the trust manager and host name verifier
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustManagers, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(resourceHostNameVerifier);
} catch (Exception e) {
Log.e(TAG, "Invalid algorithm used while setting trust store:" +e.getMessage());
throw e;
}
要实施信任管理器,只需覆盖:
- 公共无效checkClientTrusted
- 公共无效检查服务器受信任
public class ResourceTrustManager implements X509TrustManager {
private static final String TAG = ResourceTrustManager.class.getName();
protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();
public ResourceTrustManager(Collection<KeyStore> additionalkeyStores) {
final List<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();
try {
/**
* Consolidates central and aditional keystore to be used as trust managers
*/
final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
original.init((KeyStore) null);
factories.add(original);
if(additionalkeyStores != null ) {
for (KeyStore keyStore : additionalkeyStores) {
final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
additionalCerts.init(keyStore);
factories.add(additionalCerts);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
for (TrustManagerFactory tmf : factories) {
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
x509TrustManagers.add((X509TrustManager) tm);
}
}
}
ResourceAssert.hasLength(x509TrustManagers, "Could not initialize with no trust managers");
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// The default Trustmanager with default keystore
final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
defaultX509TrustManager.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for( X509TrustManager tm : x509TrustManagers ) {
try {
tm.checkServerTrusted(chain,authType);
return;
} catch( CertificateException e ) {
StringBuilder issuers = new StringBuilder();
if(chain != null){
for(X509Certificate cert :chain){
issuers.append( " " +cert.getIssuerDN().getName() );
}
}
Log.e(TAG, "Untrusted host, connection is not secure "+ issuers + "\n\n" + e.getMessage());
}
}
}
public X509Certificate[] getAcceptedIssuers() {
final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
for( X509TrustManager tm : x509TrustManagers ) {
list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
}
return list.toArray(new X509Certificate[list.size()]);
}
}
公共类ResourceTrustManager实现X509TrustManager{
私有静态最终字符串标记=ResourceTrustManager.class.getName();
受保护的ArrayList X509TrustManager=新ArrayList();
公共资源信任管理器(集合附加密钥库){
最终列表工厂=新的ArrayList();
试一试{
/**
*整合用作信托管理器的中央密钥库和传统密钥库
*/
最终TrustManagerFactory original=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
init((密钥库)null);
工厂。添加(原件);
if(additionalkeyStores!=null){
用于(密钥库密钥库:附加密钥库){
final TrustManagerFactory additionalCerts=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
附加证书初始化(密钥库);
工厂。添加(附加证书);
}
}
}捕获(例外e){
抛出新的运行时异常(e);
}
对于(TrustManagerFactory tmf:工厂){
for(TrustManager tm:tmf.getTrustManagers()){
if(X509TrustManager的tm实例){
x509TrustManagers.add((X509TrustManager)tm);
}
}
}
ResourceAssert.hasLength(X509TrustManager,“无法在没有信任管理器的情况下初始化”);
}
public void checkClientTrusted(X509Certificate[]链,字符串authType)引发CertificateException{
//具有默认密钥库的默认Trustmanager
最终X509TrustManager默认X509TrustManager=X509TrustManager.get(0);
defaultX509TrustManager.checkClientTrusted(链,authType);
}
public void checkServerTrusted(X509Certificate[]链,字符串authType)引发CertificateException{
适用于(X509TrustManager tm:X509TrustManager){
试一试{
tm.checkServerTrusted(链,authType);
返回;
}捕获(证书例外e){
StringBuilder发行人=新StringBuilder();
如果(链!=null){
对于(X509证书证书:链){
append(“+cert.getIssuerDN().getName());
}
}
Log.e(标记“不受信任的主机,连接不安全”+颁发者+“\n\n”+e.getMessage());
}
}
}
公共X509证书[]getAcceptedIssuers(){
最终ArrayList=新ArrayList();
适用于(X509TrustManager tm:X509TrustManager){
addAll(Arrays.asList(tm.getAcceptedIssuers());
}
return list.toArray(新的X509Certificate[list.size()]);
}
}
这一点也不优雅,但完成了任务。Android 4.4.2版本上有一个已知的bug,这是使用TLSv1.x协议访问HTTPS时引起的。由于不支持TLS,握手失败,因此HttpsURLConnection退回到SSLv3协议,导致握手时发生错误。我还没有找到不涉及重新实现HttpsURLConnection的TrustManager以防止错误或不安全连接的解决方案 这就是我所做的: 将自定义信任管理器提供给SSLContext:
// Trust manager that recognizes you acceptance criteria, that being ignoring handshake errors
ResourceTrustManager trustManager = new ResourceTrustManager(sslKeyStores);
TrustManager[] trustManagers = {trustManager};
// use: org.apache.http.conn.ssl.AllowAllHostnameVerifier, this can be optional depending on your case.
AllowAllHostnameVerifier resourceHostNameVerifier = new AllowAllHostnameVerifier();
// Install the trust manager and host name verifier
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustManagers, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(resourceHostNameVerifier);
} catch (Exception e) {
Log.e(TAG, "Invalid algorithm used while setting trust store:" +e.getMessage());
throw e;
}
要实施信任管理器,只需覆盖:
- 公共无效checkClientTrusted
- 公共无效检查服务器受信任
public class ResourceTrustManager implements X509TrustManager {
private static final String TAG = ResourceTrustManager.class.getName();
protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();
public ResourceTrustManager(Collection<KeyStore> additionalkeyStores) {
final List<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();
try {
/**
* Consolidates central and aditional keystore to be used as trust managers
*/
final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
original.init((KeyStore) null);
factories.add(original);
if(additionalkeyStores != null ) {
for (KeyStore keyStore : additionalkeyStores) {
final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
additionalCerts.init(keyStore);
factories.add(additionalCerts);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
for (TrustManagerFactory tmf : factories) {
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
x509TrustManagers.add((X509TrustManager) tm);
}
}
}
ResourceAssert.hasLength(x509TrustManagers, "Could not initialize with no trust managers");
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// The default Trustmanager with default keystore
final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
defaultX509TrustManager.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for( X509TrustManager tm : x509TrustManagers ) {
try {
tm.checkServerTrusted(chain,authType);
return;
} catch( CertificateException e ) {
StringBuilder issuers = new StringBuilder();
if(chain != null){
for(X509Certificate cert :chain){
issuers.append( " " +cert.getIssuerDN().getName() );
}
}
Log.e(TAG, "Untrusted host, connection is not secure "+ issuers + "\n\n" + e.getMessage());
}
}
}
public X509Certificate[] getAcceptedIssuers() {
final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
for( X509TrustManager tm : x509TrustManagers ) {
list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
}
return list.toArray(new X509Certificate[list.size()]);
}
}
公共类ResourceTrustManager实现X509TrustManager{
私有静态最终字符串标记=ResourceTrustManager.class.getName();
受保护的ArrayList X509TrustManager=新ArrayList();
公共资源信任管理器(集合附加密钥库){
最终列表工厂=新的ArrayList();
试一试{
/**
*整合用作信托管理器的中央密钥库和传统密钥库