使用Windows身份验证(AD组)保护.NET Core 3.1 API调用.NET Framework WCF服务的安全 [英] .NET Core 3.1 API Calling .NET Framework WCF Service secured using windows authentication (AD Group)

查看:162
本文介绍了使用Windows身份验证(AD组)保护.NET Core 3.1 API调用.NET Framework WCF服务的安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从.NET Core 3.1 API调用.NET Framework WCF服务(由Windows身份验证使用AD组保护),但是我收到错误消息:

I am trying to call a .NET Framework WCF Service (which is secured by Windows Authentication using an AD group) from a .NET Core 3.1 API however I am getting the error message:

System.ServiceModel.Security.MessageSecurityException:HTTP请求未经客户端身份验证方案"Negotiate"的授权.从服务器收到的身份验证标头是协商,NTLM".

System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate, NTLM'.

.NET Core API都托管在Windows上的IIS中,并且它在其下运行的应用程序池具有域帐户,该帐户位于访问所需的AD组中. 当前,我们还有其他调用WCF服务的.NET Framework应用程序,它们都可以正常工作,但这是第一个调用它的.NET Core应用程序. 部署API的服务器和部署WCF服务的服务器都存在于支持Kerberos协议的同一域中.

The .NET Core API is hosted in IIS both on windows and the app pool that it runs under has a domain account which is in the AD Group required for access. We currently have other .NET Framework applications calling the WCF service and they all work however this is the first .NET Core application to call it. Both servers which the API is deployed to and the WCF service is deployed to exist on the same domain that support Kerberos protocol.

它在本地运行时可以成功运行,但是当部署到服务器上时,它会显示上述错误消息.

It works successfully when running locally however when deployed onto a server it gives the above error message.

发生错误消息的IIS日志:

IIS Logs from the error message occuring:

POST/Broadcast.svc-8081-172.27.19.200--401 2 5 0
POST/Broadcast.svc-8081-172.27.19.200--401 1 3221225581 0

POST /Broadcast.svc - 8081 - 172.27.19.200 - - 401 2 5 0
POST /Broadcast.svc - 8081 - 172.27.19.200 - - 401 1 3221225581 0

这是API中的客户端代理创建代码:

This is the client proxy creation code in the API:

    public IWcfClient<IBroadcastService> CreateBroadcastService()
    {
        var binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
        binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Windows;

        var client = new WcfClient<IBroadcastService>(
            binding,
            new EndpointAddress($"{remoteUrl}/Broadcast.svc"));

        //My expectation is that the below line would make the call send the AppPoolIdentity Credentials?
        client.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;

        return client;
    }

WcfClient.cs(ClientBase的包装器):

WcfClient.cs (Wrapper for ClientBase):

public class WcfClient<TChannel> : ClientBase<TChannel>, IWcfClient<TChannel> where TChannel : class
{
    public WcfClient(Binding binding, EndpointAddress endpointAddress)
        : base(binding, endpointAddress)
    { }

    /// <summary>
    /// Executes a given action against <see cref="TChannel" />.
    /// </summary>
    /// <param name="invokeAction">The invocation action.</param>
    public void Invoke(Action<TChannel> invokeAction)
    {
        try
        {
            invokeAction(Channel);
            Close();
        }
        catch (CommunicationException)
        {
            Abort();
            throw;
        }
        catch (TimeoutException)
        {
            Abort();
            throw;
        }
    }

    /// <summary>
    /// Executes the given action against <see cref="TChannel" /> and returns the result.
    /// </summary>
    /// <typeparam name="TResult">The type of the result.</typeparam>
    /// <param name="invokeFunc">The invocation function.</param>
    /// <returns>An instance of <see cref="TResult" /></returns>
    public TResult Invoke<TResult>(Func<TChannel, TResult> invokeFunc)
    {
        TResult result;

        try
        {
            result = invokeFunc(Channel);
            Close();
        }
        catch (CommunicationException)
        {
            Abort();
            throw;
        }
        catch (TimeoutException)
        {
            Abort();
            throw;
        }

        return result;
    }
}

Startup.cs配置API的方法:

Startup.cs Configure method for API:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        logger.Information("Configuring application middleware...");

        if (env.IsDevelopment())
            app.UseDeveloperExceptionPage();

        app.UseSwaggerMiddleware();

        app.UseSerilogRequestLogging();

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

        ConfigCache.SetRootDirectory(Path.Combine(env.ContentRootPath, "App_Data"));

        logger.Information("Application middleware configured successfully.");
    }

用于API的Program.cs:

Program.cs for API:

public class Program
{
    [UsedImplicitly]
    public static void Main(string[] args)
    {
        var appConfig = new ConfigurationBuilder()
            // ReSharper disable once StringLiteralTypo
            .AddJsonFile("appsettings.json")
            .Build();

        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(appConfig)
            .Enrich.FromLogContext()
            .CreateLogger();

        CreateHostBuilder(args).Build().Run();
    }

    [UsedImplicitly]
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    webBuilder.UseIIS();
                    webBuilder.UseSerilog();
                });
}

.NET Framework WCF服务web.config的web.config具有指定的角色,就像这样(我已经删除了实际名称)

The web.config for the .NET Framework WCF service web.config has the specified role in like so (I have removed actual name)

<system.web>
    <authentication mode="Windows"/>
    <authorization>
      <allow roles="DOMAIN\GROUPNAME"/>
      <deny users="*"/>
    </authorization>
</system.web>

任何人都可以告诉我是否遗漏了任何东西或提供任何想法来缩小问题的范围吗? 另外,如果您需要查看代码的任何其他区域,请发表评论,我们将很乐意为您提供这些代码.

Can anyone tell me if I have missed anything or provide any ideas on how to narrow down the problem? Also please comment if you need to see any other areas of the code and will be happy to supply them.

推荐答案

它们都托管在同一台计算机上,您可能需要填充BackConnectionHostNames注册表项以禁用回送安全功能.

The fact they are both are hosted on the same machine, you may need to populate the BackConnectionHostNames registry key to disable the loopback security functionality.

步骤如下: https://stackoverflow.com/a/48086033/4813939

这篇关于使用Windows身份验证(AD组)保护.NET Core 3.1 API调用.NET Framework WCF服务的安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆