Android 7.0设备调用ASP.Net WebService出现403错误求助
解决Android 7.0设备调用ASP.Net Web服务报403错误的方案
这个问题我之前帮同行排查过类似的案例,Android 7.0在网络安全协议、证书验证逻辑上和更高版本系统有不少差异,结合你遇到的org.ksoap2.transport.HttpResponseException: HTTP request failed, HTTP status: 403错误,给你几个针对性的排查和解决方向:
1. 强制ksoap2使用TLS 1.2协议
Android 7.0虽然支持TLS 1.2,但部分旧版ksoap2库默认不会优先启用它,而很多ASP.Net Web服务现在会禁用TLS 1.0/1.1这类旧协议。你可以自定义HttpTransportSE的SSLSocketFactory来强制指定TLS 1.2:
public class TLSSocketFactory extends SSLSocketFactory { private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLSv1.2"); context.init(null, null, null); internalSSLSocketFactory = context.getSocketFactory(); } @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)); } private Socket enableTLSOnSocket(Socket socket) { if(socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"}); } return socket; } }
调用ksoap2时替换默认的SocketFactory:
HttpTransportSE transport = new HttpTransportSE(WEB_SERVICE_URL); try { SSLSocketFactory sslSocketFactory = new TLSSocketFactory(); transport.setSSLSocketFactory(sslSocketFactory); transport.call(SOAP_ACTION, envelope); } catch (Exception e) { e.printStackTrace(); }
2. 适配Android 7.0的网络安全配置
Android 7.0引入了Network Security Configuration机制,如果你的ASP.Net服务使用自签名证书或未被系统信任的CA证书,系统会拦截请求,部分服务端会返回403而非明确的证书错误。你可以这样配置:
- 在
res/xml目录下创建network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> <trust-anchors> <!-- 信任系统默认证书 --> <certificates src="system" /> <!-- 如果是自签名证书,添加下面的配置(替换成你的证书路径) --> <certificates src="@raw/your_self_signed_cert" /> </trust-anchors> </base-config> </network-security-config>
- 在
AndroidManifest.xml的<application>标签中引用该配置:
android:networkSecurityConfig="@xml/network_security_config"
3. 排查服务端的请求拦截规则
既然其他设备正常,大概率是Android 7.0的请求特征触发了ASP.Net服务端的拦截策略:
- 检查服务端Web.config中的
<authorization>配置,是否有IP或User-Agent的限制; - 查看IIS日志中该设备的请求记录,确认403的子状态码(比如403.7是客户端证书要求,403.13是客户端证书被吊销);
- 尝试在ksoap2请求中添加和正常设备一致的User-Agent头:
transport.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36");
4. 升级ksoap2库版本
旧版本的ksoap2(比如2.6.0及更早)在Android 7.0+系统上存在不少兼容性问题,建议升级到最新稳定版,比如在build.gradle中添加:
implementation 'com.google.code.ksoap2-android:ksoap2-android:3.6.4'
内容的提问来源于stack exchange,提问作者jpussacq




