调用WSDL获取SOAP响应时遭遇401未授权错误求助
从你给出的错误信息The HTTP request is unauthorized with client authentication scheme 'Anonymous'.The authentication header received from the server was 'Basic Realm’=myrealm可以明确:目标服务器要求的是HTTP Basic认证,而你当前的WCF配置使用的是TransportWithMessageCredential(消息层用户名密码),这和服务器的认证要求不匹配,导致了401错误。
下面是具体的修复步骤:
1. 修正WCF配置(统一使用正确的basicHttpBinding)
你现在同时在WcfClient和主程序里用了不同的绑定配置(customBinding和basicHttpBinding),这会导致配置冲突,需要统一改成适配Basic认证的配置:
替换主程序和WcfClient的app.config中的绑定配置
删除原有的customBinding和错误的basicHttpBinding配置,替换为以下内容:
<basicHttpBinding> <binding name="rmt_wsBinding1" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"> <!-- 因为是HTTPS传输,mode设为Transport,启用HTTP Basic认证 --> <security mode="Transport"> <transport clientCredentialType="Basic" /> </security> </binding> </basicHttpBinding> <client> <endpoint address="https://www1.gsis.gr/wsicispay/rmt_ws" binding="basicHttpBinding" bindingConfiguration="rmt_wsBinding1" contract="IcisPayments.rmt_ws" name="rmt_ws" /> </client>
security mode="Transport":因为服务地址是HTTPS,传输层加密,同时在传输层做认证transport clientCredentialType="Basic":明确告诉WCF使用HTTP Basic认证方式,这正好匹配服务器返回的Basic Realm要求
2. 优化调用代码
你的代码里重复创建了客户端实例,而且可以简化一些细节:
// 直接using包裹客户端,自动管理生命周期 using (rmt_wsClient rmt_wsClient = new rmt_wsClient()) { // 强制使用TLS 1.2(对应3072,这部分你的代码是对的) ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // 设置Basic认证的用户名密码 rmt_wsClient.ClientCredentials.UserName.UserName = UserName; rmt_wsClient.ClientCredentials.UserName.Password = Password; string messageToSend = "<wsTin>" + wsTin + "</wsTin><wsUser>" + wsUser + "</wsUser>" + "<wsPswd>" + wsPswd + "</wsPswd><contain><bmrn>" + bmrn + "</bmrn><blrn>" + blrn + "</blrn><bcnt>" + bcnt + "</bcnt><bafm>" + "bafm" + "</bafm></contain>"; // 不需要手动调用Open(),WCF会自动打开连接 string responsed = rmt_wsClient.remittanceXml(messageToSend); rtn = responsed; }
- 去掉了多余的
rmt_ws client = new rmt_wsClient(); - 不需要手动调用
Open(),WCF在调用服务方法时会自动处理连接的打开和关闭 - 确保
UserName和Password是服务器要求的Basic认证凭据(注意和你XML里的wsUser/wsPswd区分开,这两个是业务参数,而Basic认证的凭据是服务器端验证身份用的账号密码)
3. 关键注意事项
- 区分两种凭据:你代码里的
wsUser/wsPswd是业务参数(放在SOAP消息体里),而ClientCredentials.UserName/Password是HTTP Basic认证的凭据(放在请求头里),这是两个完全不同的东西,不要混淆 - 统一配置:确保WcfClient项目和主项目的app.config配置完全一致,避免配置不一致导致的问题
- TLS版本:你设置的
(SecurityProtocolType)3072对应TLS 1.2,这部分是正确的,因为很多现代服务器不再支持旧的TLS版本
4. 验证步骤
- 保存修改后的配置和代码
- 清理并重建整个解决方案
- 运行程序,检查是否还会出现401错误
如果还是有问题,可以通过Fiddler抓包,查看请求头里是否包含Authorization: Basic xxxxx(xxxxx是用户名密码Base64编码后的字符串),确认认证头是否正确发送。
内容的提问来源于stack exchange,提问作者rippergr
相关产品推荐
相关产品推荐

