Azure SQL Database仅Android 11可访问?低版本安卓连接失败如何解决
根因说明
Azure SQL Database 目前已强制禁用 TLS 1.0、TLS 1.1 协议,仅支持 TLS 1.2 及以上版本的加密连接。Android 11 系统默认启用 TLS 1.2 作为默认协商协议,所以连接正常;Android 10 及更低版本虽然系统层面支持 TLS 1.2,但部分版本未将其设为默认启用的协议,SSL 握手时协商到低版本 TLS 就会被 Azure SQL 拒绝,这是问题的核心原因。
具体修复步骤
步骤1:修改数据库连接字符串,强制指定 TLS 版本
如果你使用官方 JDBC 驱动连接 Azure SQL,在连接字符串中新增参数指定 TLS 版本,示例如下:jdbc:sqlserver://<你的服务器名>.database.windows.net:1433;database=<你的库名>;user=<用户名>;password=<密码>;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;sslProtocol=TLSv1.2
核心新增参数为sslProtocol=TLSv1.2,强制驱动使用 TLS 1.2 发起连接。步骤2:为低版本 Android 主动启用 TLS 1.2
对 Android 8.0 到 Android 9.0 版本,需要自定义 SSLSocketFactory 强制启用 TLS 1.2,再配置到连接驱动中,示例代码如下:public class TLSSocketFactory extends SSLSocketFactory { private final SSLSocketFactory delegate; public TLSSocketFactory() throws NoSuchAlgorithmException, KeyManagementException { SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); delegate = sslContext.getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return enableTLS12(delegate.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException { return enableTLS12(delegate.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { return enableTLS12(delegate.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return enableTLS12(delegate.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return enableTLS12(delegate.createSocket(address, port, localAddress, localPort)); } private Socket enableTLS12(Socket socket) { if (socket instanceof SSLSocket) { ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"}); } return socket; } }配置时将该自定义 SSLSocketFactory 传入 JDBC 连接的属性配置即可。
步骤3:配置应用网络安全规则
在res/xml目录下新增network_security_config.xml文件,明确允许 Azure SQL 域名使用 TLS 1.2 连接:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">database.windows.net</domain> <tls-config> <protocols> <protocol>TLSv1.2</protocol> <protocol>TLSv1.3</protocol> </protocols> </tls-config> </domain-config> </network-security-config>之后在
AndroidManifest.xml的application标签中添加属性:android:networkSecurityConfig="@xml/network_security_config"步骤4:更新连接驱动版本
确保你使用的 SQL Server 连接驱动为官方最新稳定版,旧版本驱动不支持强制指定 TLS 协议的相关参数。
额外安全建议
不建议在客户端直接直连 Azure SQL 数据库,存储在 APK 中的数据库连接密钥极易被反编译窃取,造成数据泄露。更合理的方案是封装一层后端服务接口,客户端仅通过接口完成数据操作。
内容的提问来源于stack exchange,提问作者user16860131

