Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
197 views
in Technique[技术] by (71.8m points)

c# - .NET Core 3.1 API Calling .NET Framework WCF Service secured using windows authentication (AD Group)

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: The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate, NTLM'.

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 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

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 (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 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.");
    }

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();
                });
}

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="DOMAINGROUPNAME"/>
      <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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

Steps here: https://stackoverflow.com/a/48086033/4813939


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...