You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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而非明确的证书错误。你可以这样配置:

  1. 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>
  1. 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

火山引擎 最新活动