WCF调用Webservice切换域名后出现Negotiate认证错误如何解决
报错原因
- SPN(服务主体名称)注册缺失
Windows集成认证使用Negotiate协商机制时优先走Kerberos协议,Kerberos要求服务端必须在AD中注册对应访问域名的SPN到运行服务的账号下。你之前使用局域网IP访问时,Kerberos不识别IP作为合法SPN,会自动降级到NTLM认证,因此原有配置可以正常运行;更换为域名后客户端默认尝试使用Kerberos认证,服务端缺失对应SPN就会返回协商失败的异常认证头。
浏览器能正常访问是因为浏览器对Windows认证的协商降级逻辑更宽松,Kerberos失败后会自动回退到NTLM重试,而WCF客户端默认配置不会自动降级,因此直接抛出异常。 - 服务端IIS配置差异
站点绑定域名后,Windows认证的提供程序优先级、内核模式认证配置和之前IP绑定的站点配置不一致,比如开启了内核模式认证但未给对应账号配置正确的SPN,也会触发该错误。 - Kerberos缓存冲突
客户端或服务端存在旧的IP访问对应的Kerberos票据缓存,和新域名的认证请求冲突,导致认证票据无效。
排查解决步骤
- 第一步:临时验证是否为Kerberos协商问题
修改客户端绑定配置,强制WCF走NTLM认证,绕过Kerberos协商:
<binding name="My_Binding" maxReceivedMessageSize="10485760"> <security mode="Transport"> <transport clientCredentialType="Windows" /> </security> <!-- 新增如下配置强制使用NTLM --> <security> <localClientSettings> <authenticationSchemeMapping Negotiate="Ntlm" /> </localClientSettings> </security> </binding>
修改后如果调用正常,即可确认是SPN缺失导致的Kerberos认证失败,你可以选择继续使用NTLM配置,或者按后续步骤注册SPN修复Kerberos认证。
- 第二步:注册对应域名的SPN
联系域管理员在AD服务器上执行以下命令,给Webservice应用池的运行账号注册对应域名的SPN:
# HTTP协议通用配置 setspn -S HTTP/你的Webservice完整域名 域\应用池运行账号 # 若使用HTTPS访问可额外添加 setspn -S HTTPS/你的Webservice完整域名 域\应用池运行账号
如果你的IIS站点开启了内核模式认证,需要将SPN注册到服务器的计算机账号而非应用池账号:
setspn -S HTTP/你的Webservice完整域名 域\服务器计算机名$
- 第三步:检查IIS站点认证配置
- 进入IIS站点的「身份验证」模块,右键点击「Windows身份验证」选择「提供程序」,确认可用提供程序顺序为
Negotiate在上、NTLM在下,无其他多余的认证提供程序。 - 右键点击「Windows身份验证」选择「高级设置」,如果使用自定义域账号运行应用池,可先临时取消勾选「内核模式身份验证」测试是否恢复正常。
- 第四步:清理Kerberos认证缓存
分别在客户端和服务端执行命令清理本地Kerberos票据缓存,之后重启客户端程序和服务端应用池重新测试:klist purge
内容的提问来源于stack exchange,提问作者El_Shaddai
相关产品推荐
相关产品推荐

