根据Android中关于SSLSocket
和SSLContext
的文档,TLS v1。1和v1。API级别16支持2个协议,但默认情况下不启用。http://developer.android.com/reference/javax/net/ssl/SSLSocket.html http://developer.android.com/reference/javax/net/ssl/SSLContext.html
如何在运行Android 4.1或更高版本(但低于5.0)的设备上启用它?
我曾尝试创建一个自定义SSLSocketFactory,在创建套接字时启用所有受支持的协议,然后将我的自定义实现用作:
HttpsURLConnection.setDefaultSSLSocketFactory(新的MySSLSocketFactory());
public class MySSLSocketFactory extends SSLSocketFactory {
private SSLContext sc;
private SSLSocketFactory ssf;
public MySSLSocketFactory() {
try {
sc = SSLContext.getInstance("TLS");
sc.init(null, null, null);
ssf = sc.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
throws IOException {
SSLSocket ss = (SSLSocket) ssf.createSocket(s, host, port, autoClose);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public String[] getDefaultCipherSuites() {
return ssf.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return ssf.getSupportedCipherSuites();
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
SSLSocket ss = (SSLSocket) ssf.createSocket(host, port);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
SSLSocket ss = (SSLSocket) ssf.createSocket(host, port);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
throws IOException, UnknownHostException {
SSLSocket ss = (SSLSocket) ssf.createSocket(host, port, localHost, localPort);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
int localPort) throws IOException {
SSLSocket ss = (SSLSocket) ssf.createSocket(address, port, localAddress, localPort);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
}
但是,当试图与仅启用TLS 1.2的服务器建立连接时,它仍然会给出异常。
以下是我得到的一个例外:
03-09:21:38.427:W/系统。err(2496):javax。网ssl。SSLHandshakeException:javax。网ssl。SSLProtocolException:SSL握手中止:SSL=0xb7fa0620:SSL库中出现故障,通常是协议错误
03-09:21:38.427:W/系统。err(2496):错误:14077410:SSL例程:SSL23_GET_SERVER_HELLO:sslv3警报握手失败(外部/openssl/SSL/s23_clnt.c:741 0xa90e6990:0x00000000)
在Androidbuild中添加
:play services safetynet
library。格雷德尔
implementation 'com.google.android.gms:play-services-safetynet:+'
并将此代码添加到您的MainApplication.java
:
@Override
public void onCreate() {
super.onCreate();
upgradeSecurityProvider();
SoLoader.init(this, /* native exopackage */ false);
}
private void upgradeSecurityProvider() {
ProviderInstaller.installIfNeededAsync(this, new ProviderInstallListener() {
@Override
public void onProviderInstalled() {
}
@Override
public void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {
// GooglePlayServicesUtil.showErrorNotification(errorCode, MainApplication.this);
GoogleApiAvailability.getInstance().showErrorNotification(MainApplication.this, errorCode);
}
});
}
我按照文章中提供的指示解决了这个问题http://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/没什么变化。
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
SSLSocketFactory noSSLv3Factory = null;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
noSSLv3Factory = new TLSSocketFactory(sslContext.getSocketFactory());
} else {
noSSLv3Factory = sslContext.getSocketFactory();
}
connection.setSSLSocketFactory(noSSLv3Factory);
这是定制TLSSocketFactory的代码:
public static class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory(SSLSocketFactory delegate) throws KeyManagementException, NoSuchAlgorithmException {
internalSSLSocketFactory = delegate;
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
/*
* Utility methods
*/
private static Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)
&& isTLSServerEnabled((SSLSocket) socket)) { // skip the fix if server doesn't provide there TLS version
((SSLSocket) socket).setEnabledProtocols(new String[]{TLS_v1_1, TLS_v1_2});
}
return socket;
}
private static boolean isTLSServerEnabled(SSLSocket sslSocket) {
System.out.println("__prova__ :: " + sslSocket.getSupportedProtocols().toString());
for (String protocol : sslSocket.getSupportedProtocols()) {
if (protocol.equals(TLS_v1_1) || protocol.equals(TLS_v1_2)) {
return true;
}
}
return false;
}
}
编辑:感谢ademar111190实现kotlin(链接)
class TLSSocketFactory constructor(
private val internalSSLSocketFactory: SSLSocketFactory
) : SSLSocketFactory() {
private val protocols = arrayOf("TLSv1.2", "TLSv1.1")
override fun getDefaultCipherSuites(): Array<String> = internalSSLSocketFactory.defaultCipherSuites
override fun getSupportedCipherSuites(): Array<String> = internalSSLSocketFactory.supportedCipherSuites
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean) =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose))
override fun createSocket(host: String, port: Int) =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port))
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int) =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort))
override fun createSocket(host: InetAddress, port: Int) =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port))
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int) =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort))
private fun enableTLSOnSocket(socket: Socket?) = socket?.apply {
if (this is SSLSocket && isTLSServerEnabled(this)) {
enabledProtocols = protocols
}
}
private fun isTLSServerEnabled(sslSocket: SSLSocket) = sslSocket.supportedProtocols.any { it in protocols }
}
2种启用TLSv1的方法。1和TLSv1。2:
schemeRegistry.register(新方案("https", new TlsSniSocketFactory(), port));
问题内容: 我是一名Android开发人员,我想在我的应用程序中编写一条语句。在此语句中,我要检查默认浏览器(Android OS中 问题答案: 添加下面的Helper类: 现在,你可以从以下代码中检查所需的应用程序是否正在运行:
我正在Android应用程序中创建一个项目。我已经在java eclipse环境中将java jdt ast作为独立应用程序实现了,并且我在控制台输出上得到了我需要的东西。现在我想把这个代码运行到我的Android应用程序项目中。但是,当我在文本中设置所有输出时,当我启动应用程序时,Android的视图,不幸的是它停止了,我不知道为什么...有人会知道为什么会发生这种情况吗?感谢您的帮助。 代码没
问题内容: 我正在用Java开发使用Lua脚本的Android游戏。为了执行这些脚本,我将LuaJ与Java的ScriptEngine类一起使用。例如… 但是,Android显然不支持此功能(这与android没有完整的JVM有关,我在某处读过)。有什么方法可以在Android上使用Lua脚本吗?也许有一个LuaJ替代方案?也许有一种直接使用LuaJ编译和执行Lua脚本的方法(尽管我看不到如何)。
我需要在具有自签名证书的Spring Boot 2.0.5应用程序上启用HTTPS,然而,到目前为止,我在配置中发现的所有内容都与设置一个名为的属性有关,但在这个Spring Boot版本上,该属性似乎不推荐使用...在Spring Boot应用程序上启用HTTPS还有其他方法吗?
问题内容: 我创建了新的libgdx项目,并且想在Android Studio中运行桌面应用程序。与运行配置有关吗?在Eclipse中,我可以选择“以Java应用程序运行”。 问题答案: 好吧,我做到了。这是解决方案https://github.com/libgdx/libgdx/wiki/Gradle-and-Intellij- IDEA#running-your-project ,单击加号()
我用JDK 13制作了一个java应用程序。我用launch4j创建了一个exe文件。但是没有人可以运行它,因为每个人都有jre 1.8版本,而且它不会启动。。。我必须在安装中包含java jdk 13,并用它设置java_home?