Android使用Ksoap2调用带BasicHttpBinding认证的WCF服务失败
我之前帮朋友排查过几乎一模一样的问题,你的C#代码能正常跑,但Android端用ksoap2死活连不上,大概率是踩了这几个常见的坑,咱们一步步来解决:
1. 修复Base64编码的换行问题
这是最容易踩的坑!org.kobjects.base64.Base64.encode方法默认会在每76个字符后插入换行符,但HTTP的Authorization头要求是连续无换行的Base64字符串,换行会直接导致服务端解析认证信息失败。
替换成Android原生的Base64工具类(API 8及以上支持),指定NO_WRAP参数避免换行:
// 替换原来的HeaderProperty添加代码 String credentials = "admin:adminpass"; // 用UTF-8编码,避免乱码导致认证失败 byte[] credBytes = credentials.getBytes(StandardCharsets.UTF_8); // NO_WRAP确保生成的Base64字符串没有换行符 String base64Auth = Base64.encodeToString(credBytes, Base64.NO_WRAP); header.add(new HeaderProperty("Authorization", "Basic " + base64Auth));
2. 验证SOAP Action的正确性
WCF的BasicHttpBinding对SOAP Action的要求非常严格,你拼接的http://tempuri.org/IMobilService/LoginServiceTest必须和WCF契约里定义的完全一致。
你可以访问WCF服务的WSDL地址(https://xxx.xxx.com.tr/testBasicHttpBinding/MobilService.svc?wsdl),找到LoginServiceTest方法对应的soap:action属性,确认是否和你代码里的一致。如果不一致,直接替换成WSDL里的正确值。
3. 处理HTTPS证书验证问题
如果你的服务用的是HTTPS,且证书是自签名或者非权威CA颁发的,Android默认会拒绝连接,这也会导致调用失败。
测试环境临时方案(仅用于测试,生产环境绝对禁用)
可以自定义一个忽略证书验证的HttpClient,传给HttpTransportSE:
// 创建信任所有证书的TrustManager TrustManager trustAllCerts = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; // 初始化SSL上下文 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{trustAllCerts}, new SecureRandom()); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); // 创建自定义HttpClient HttpClient httpClient = HttpClientBuilder.create() .setSSLSocketFactory(sslSocketFactory) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .setConnectionTimeToLive(timeOut, TimeUnit.MILLISECONDS) .build(); // 使用自定义HttpClient初始化HttpTransportSE HttpTransportSE aht = new HttpTransportSE(httpClient, "https://xxx.xxx.com.tr/testBasicHttpBinding/MobilService.svc", timeOut);
生产环境方案
请务必使用权威CA颁发的证书,或者将服务器证书导入到Android应用的信任存储中,避免安全风险。
4. 优化响应获取逻辑
你当前用envelope.bodyIn获取响应,这会拿到整个SOAP Body对象,不如直接用envelope.getResponse()更直接,它会返回服务端返回的具体结果:
// 替换原来的result获取代码 Object result = envelope.getResponse(); resultData = result.toString();
最后再检查几个细节
- 确保
envelope.dotNet = true;没有被注释,这个设置是ksoap2适配.NET服务的关键。 - 确认你的
LoginServiceTest方法确实不需要参数(如果需要参数,要保证parameters列表正确传递了所有必填参数)。
按照上面的步骤修改后,应该就能正常调用WCF服务了。
内容的提问来源于stack exchange,提问作者Erdinç Ayvaz

