使用MStest框架调用Kerberos认证WSDL接口配置凭证后报401未授权问题
错误原因
- 待对接接口采用Kerberos认证,但现有代码中注入了Basic类型的Authorization头,且未对WCF客户端绑定配置Kerberos认证方案,WCF客户端识别到服务端认证要求未被正确匹配,默认使用Anonymous身份发起请求,因此返回401未授权。
- 代码中传递的client_id、client_secret为OAuth2体系参数,和Kerberos认证流程无关,如无额外业务要求无需传递。
修复步骤
- 调整WCF绑定安全配置,指定Kerberos认证模式
根据你使用的绑定类型修改安全配置,核心是将客户端凭证类型设置为Windows(对应Kerberos认证):
// 若使用BasicHttpBinding var binding = APIClient.Endpoint.Binding as BasicHttpBinding; // HTTP场景用TransportCredentialOnly,HTTPS场景替换为Transport binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; // 若使用WSHttpBinding请替换为下方配置 // var binding = APIClient.Endpoint.Binding as WSHttpBinding; // binding.Security.Mode = SecurityMode.Message; // binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
- 删除无效的Basic认证头注入代码
移除手动构造Basic Authorization头的代码,避免干扰WCF原生Kerberos认证流程,对应删除以下代码行:
_httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(APIClient.ClientCredentials.UserName.UserName + ":" + OrionAPIClient.ClientCredentials.UserName.Password));
- 替换为Kerberos凭证配置
原ClientCredentials.UserName为Basic认证专用配置,Kerberos场景需使用Windows凭证配置:
// 域名参数可根据实际情况省略 APIClient.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("userabc", "passabc", "你的域名称"); APIClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
- 确认服务端SPN配置(可选排查项)
Kerberos认证要求客户端请求地址和服务端注册的SPN匹配,如服务地址为http://api.xxx.com/service,服务端需注册对应SPN:HTTP/api.xxx.com,SPN不匹配也会触发401错误。
调整后完整测试代码
[TestMethod] public void GetUsers() { APIClient= new AutoStudioFW.APIService.APIServiceclient(); System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; // 测试环境临时跳过证书校验,生产环境建议删除 System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; // 配置Kerberos认证绑定 var binding = APIClient.Endpoint.Binding as BasicHttpBinding; binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; // 配置Kerberos凭证 APIClient.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("userabc", "passabc"); APIClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation; _httpRequestProperty = new HttpRequestMessageProperty(); // 如确认业务需要client_id、client_secret可保留,否则删除以下两行 _httpRequestProperty.Headers.Add("client_id", "01ab34cd"); _httpRequestProperty.Headers.Add("client_secret", "abc123secret"); using (scope = new System.ServiceModel.OperationContextScope(APIClient.InnerChannel)) { System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = _httpRequestProperty; var GetUser = APIClient.getCurrentUser("555"); } }
内容的提问来源于stack exchange,提问作者Zaheer Khan
相关产品推荐
相关产品推荐

