Android 7.0 : 'javax.net.ssl.SSLHandshakeException: 连接被对端关闭
Android 7.0 : 'javax.net.ssl.SSLHandshakeException: Connection closed by peer
当我尝试从我的应用程序访问 'https' 网络服务时,出现“javax.net.ssl.SSLHandshakeException:连接被对等方关闭”错误.相同的 Web 服务在 Chrome 浏览器中运行良好。
此问题仅在 Android 7.0 上发生,在 Android 6.0 和 5.0 中运行良好。
服务器是 CA 认证的,不是自签名的。
尝试使用此代码,它对我有用:
private static void initializeSSLContext(Context mContext){
try {
SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
ProviderInstaller.installIfNeeded(mContext.getApplicationContext());
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
不要忘记使用 google 安全库 :
compile 'com.google.android.gms:play-services-safetynet:11.6.2'
我不得不使用扩展的 SSLSocket class 来包含所有协议和密码套件以解决这个问题。解决方案在于 GetProtocolList() & GetCipherList()
private static OkHttpClient.Builder enableAllProtocols(OkHttpClient.Builder client) {
try {
client.sslSocketFactory(new SSLSocketFactoryExtended(), provideX509TrustManager());
} catch (Exception exc) {
Log.e("OkHttpTLSCompat", "Error while setting Protocols", exc);
}
return client;
}
SSLSocketFactoryExtended Class 文件
public class SSLSocketFactoryExtended extends SSLSocketFactory {
private SSLContext mSSLContext;
private String[] mCiphers;
private String[] mProtocols;
public SSLSocketFactoryExtended() throws NoSuchAlgorithmException, KeyManagementException {
initSSLSocketFactoryEx(null,null,null);
}
public String[] getDefaultCipherSuites() {
return mCiphers;
}
public String[] getSupportedCipherSuites() {
return mCiphers;
}
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
@Override
public Socket createSocket(String host, int port) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
mSSLContext = SSLContext.getInstance("TLS");
mSSLContext.init(km, tm, random);
mProtocols = GetProtocolList();
mCiphers = GetCipherList();
}
protected String[] GetProtocolList() {
String[] protocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
String[] availableProtocols = null;
SSLSocket socket = null;
try {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
socket = (SSLSocket)factory.createSocket();
availableProtocols = socket.getSupportedProtocols();
} catch(Exception e) {
return new String[]{ "TLSv1" };
} finally {
if(socket != null)
try {
socket.close();
} catch (IOException e) {
}
}
List<String> resultList = new ArrayList<String>();
for(int i = 0; i < protocols.length; i++) {
int idx = Arrays.binarySearch(availableProtocols, protocols[i]);
if(idx >= 0)
resultList.add(protocols[i]);
}
return resultList.toArray(new String[0]);
}
protected String[] GetCipherList() {
List<String> resultList = new ArrayList<String>();
SSLSocketFactory factory = mSSLContext.getSocketFactory();
for(String s : factory.getSupportedCipherSuites()){
resultList.add(s);
}
return resultList.toArray(new String[resultList.size()]);
}
}
当我尝试从我的应用程序访问 'https' 网络服务时,出现“javax.net.ssl.SSLHandshakeException:连接被对等方关闭”错误.相同的 Web 服务在 Chrome 浏览器中运行良好。
此问题仅在 Android 7.0 上发生,在 Android 6.0 和 5.0 中运行良好。
服务器是 CA 认证的,不是自签名的。
尝试使用此代码,它对我有用:
private static void initializeSSLContext(Context mContext){
try {
SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
ProviderInstaller.installIfNeeded(mContext.getApplicationContext());
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
不要忘记使用 google 安全库 :
compile 'com.google.android.gms:play-services-safetynet:11.6.2'
我不得不使用扩展的 SSLSocket class 来包含所有协议和密码套件以解决这个问题。解决方案在于 GetProtocolList() & GetCipherList()
private static OkHttpClient.Builder enableAllProtocols(OkHttpClient.Builder client) {
try {
client.sslSocketFactory(new SSLSocketFactoryExtended(), provideX509TrustManager());
} catch (Exception exc) {
Log.e("OkHttpTLSCompat", "Error while setting Protocols", exc);
}
return client;
}
SSLSocketFactoryExtended Class 文件
public class SSLSocketFactoryExtended extends SSLSocketFactory {
private SSLContext mSSLContext;
private String[] mCiphers;
private String[] mProtocols;
public SSLSocketFactoryExtended() throws NoSuchAlgorithmException, KeyManagementException {
initSSLSocketFactoryEx(null,null,null);
}
public String[] getDefaultCipherSuites() {
return mCiphers;
}
public String[] getSupportedCipherSuites() {
return mCiphers;
}
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
@Override
public Socket createSocket(String host, int port) throws IOException {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port);
ss.setEnabledProtocols(mProtocols);
ss.setEnabledCipherSuites(mCiphers);
return ss;
}
private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
mSSLContext = SSLContext.getInstance("TLS");
mSSLContext.init(km, tm, random);
mProtocols = GetProtocolList();
mCiphers = GetCipherList();
}
protected String[] GetProtocolList() {
String[] protocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
String[] availableProtocols = null;
SSLSocket socket = null;
try {
SSLSocketFactory factory = mSSLContext.getSocketFactory();
socket = (SSLSocket)factory.createSocket();
availableProtocols = socket.getSupportedProtocols();
} catch(Exception e) {
return new String[]{ "TLSv1" };
} finally {
if(socket != null)
try {
socket.close();
} catch (IOException e) {
}
}
List<String> resultList = new ArrayList<String>();
for(int i = 0; i < protocols.length; i++) {
int idx = Arrays.binarySearch(availableProtocols, protocols[i]);
if(idx >= 0)
resultList.add(protocols[i]);
}
return resultList.toArray(new String[0]);
}
protected String[] GetCipherList() {
List<String> resultList = new ArrayList<String>();
SSLSocketFactory factory = mSSLContext.getSocketFactory();
for(String s : factory.getSupportedCipherSuites()){
resultList.add(s);
}
return resultList.toArray(new String[resultList.size()]);
}
}