You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CoreWCF服务迁移后WCF客户端NTLM身份认证401问题求助

问题:CoreWCF迁移后WCF客户端返回401认证失败,REST接口正常

背景

我正在将托管多个REST API和WCF接口的.NET 4.8应用迁移至ASP.NET Core(.NET 8),使用CoreWCF迁移WCF接口。因客户端存在大量依赖,无法修改客户端代码。

REST客户端(正常工作)

REST请求的客户端代码可正常调用迁移后的服务:

using (HttpClientHandler handler = new HttpClientHandler())
{
    handler.UseDefaultCredentials = true;

    using (HttpClient client = new HttpClient(handler))
    {
        var response = client.GetAsync($"https://localhost:44375/api/interfaces").Result;      
    }
}

WCF客户端(返回401错误)

绑定初始化代码

private static void EnsureWCFServiceBindings()
{
     if (transportBinding == null)
     {
         XmlDictionaryReaderQuotas readerQuotas = new XmlDictionaryReaderQuotas();
         readerQuotas.MaxDepth = 2147483647;
         readerQuotas.MaxStringContentLength = 2147483647;
         readerQuotas.MaxArrayLength = 2147483647;
         readerQuotas.MaxBytesPerRead = 2147483647;
         readerQuotas.MaxNameTableCharCount = 2147483647;

         HttpTransportSecurity httpTransportSecurity = new HttpTransportSecurity();
         httpTransportSecurity.ClientCredentialType = HttpClientCredentialType.Ntlm;
         httpTransportSecurity.ProxyCredentialType = HttpProxyCredentialType.Ntlm;
         httpTransportSecurity.Realm = "mydomain.com";

         BasicHttpMessageSecurity basicHttpMessageSecurity = new BasicHttpMessageSecurity();
         basicHttpMessageSecurity.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
         basicHttpMessageSecurity.AlgorithmSuite = SecurityAlgorithmSuite.Default;

         BasicHttpsSecurity basicHttpsSecurity = new BasicHttpsSecurity
         {
             Mode = BasicHttpsSecurityMode.Transport, 
             Transport = httpTransportSecurity, 
             Message = basicHttpMessageSecurity
         };

         BasicHttpsBinding basicHttpsBinding = new BasicHttpsBinding
         {
             CloseTimeout = TimeSpan.FromMinutes(5), 
             OpenTimeout = TimeSpan.FromMinutes(5), 
             ReceiveTimeout = TimeSpan.FromMinutes(10),
             SendTimeout = TimeSpan.FromMinutes(5),
             AllowCookies = false, 
             BypassProxyOnLocal = false,
             HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
             MaxBufferSize = 2147483647, 
             MaxBufferPoolSize = 0,
             MaxReceivedMessageSize = 2147483647,
             MessageEncoding = WSMessageEncoding.Text, 
             TextEncoding = Encoding.UTF8, 
             TransferMode = TransferMode.Buffered, 
             ReaderQuotas = readerQuotas,
             Security = basicHttpsSecurity
         };
         transportBinding = basicHttpsBinding;
     }

     if (clientBuildClient == null)
     {          
         clientBuildClient = new EndpointAddress(string.Format("{0}{1}", "https://localhost:44375/", "BuildClient.svc"));
     }
 }

调用代码

MyCommunicationClient myClient = new MyCommunicationClient(WCFBindings.TransportBinding, WCFBindings.EndPointBuildClient);
ResultObject response = myClient.CallService(serviceRequestParameter);

服务端Program.cs配置

builder.Services.AddHttpContextAccessor();
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
    options.AddPolicy("RequireWindowsAuth", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.AddAuthenticationSchemes(NegotiateDefaults.AuthenticationScheme);
    });
});

builder.WebHost.UseIISIntegration();
// some more code here
app.UseServiceModel(serviceBuilder =>
{
   serviceBuilder.AddService<BuildClient>((serviceOptions) => { })
        .AddServiceEndpoint<BuildClient, IBuildClient>(new BasicHttpBinding
        {
            Security = new BasicHttpSecurity
            {
                Mode = BasicHttpSecurityMode.Transport,
                Transport = new HttpTransportSecurity
                {
                    ClientCredentialType = HttpClientCredentialType.Windows,
                    AlwaysUseAuthorizationPolicySupport = true,
                    Realm = "mydomain.com"
                }
            }
        }, "/BuildClient.svc");
    });

    var serviceMetadataBehavior = app.Services.GetRequiredService<ServiceMetadataBehavior>();
    serviceMetadataBehavior.HttpGetEnabled = true;
    serviceMetadataBehavior.HttpsGetEnabled = true;
    
    IHttpContextAccessor httpContextAccessor = app.Services.GetRequiredService<IHttpContextAccessor>();
    IdentityProvider.Configure(httpContextAccessor);
    
app.UseAuthentication();
app.UseAuthorization();

IIS Express配置

{
    "iisSettings": {
        "windowsAuthentication": true,
        "anonymousAuthentication": false,
        "iisExpress": {
            "applicationUrl": "http://localhost:50228",
            "sslPort": 44375
        }
    },
    "profiles": {
        "IIS Express": {
            "commandName": "IISExpress",
            "launchBrowser": true,
            "launchUrl": "swagger",
            "environmentVariables": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            }
        }
    },
    "BuildService": {
        "commandName": "Project",
        "dotnetRunMessages": true,
        "launchBrowser": true,
        "applicationUrl": "http://localhost:50228;https://localhost:44375",
        "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
        }
    }
}

已尝试的操作

  • 自定义NtlmAuthenticationHandler后,REST请求可正常认证,但WCF请求仍无用户信息且返回401。
  • 尝试多种HttpClientCredentialType配置均无效。

需求

求指导如何配置服务端使WCF调用能正确认证用户。


内容的提问来源于stack exchange,提问作者Tomtom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:54:50