使用外部 WCF 服务时,在 docker 内运行的 Dotnet 核心 Web api 无法进行身份验证

Posted

技术标签:

【中文标题】使用外部 WCF 服务时,在 docker 内运行的 Dotnet 核心 Web api 无法进行身份验证【英文标题】:Dotnet core web api running inside docker fails to authenticate when consuming external WCF service 【发布时间】:2018-02-27 01:57:00 【问题描述】:

我正在使用 dotnet core 1.1.2 构建一个 RESTful API。

这个 api 的很大一部分需要向外部 WCF 服务发出请求。这些请求使用基于 Windows 的用户名、密码和域的身份验证进行身份验证。

我目前正在准备 api 生产,我想尝试对其进行 docker 化。

我遇到的问题是,一旦从 docker 容器中调用此第三方 WCF 服务,身份验证就会失败。使用 dotnet 运行时运行 API 可以在 windows 和 mac 上运行,并且服务会得到应有的身份验证。

我使用 Visual Studio 2017 的 Connect wcf 服务功能使用 WCF 服务,然后使用正确的身份验证修改端点绑定 模式。

public ServiceSoapClient(EndpointConfiguration endpointConfiguration, string username, string password, string domain) :
base(ServiceSoapClient.GetBindingForEndpoint(endpointConfiguration), ServiceSoapClient.GetEndpointAddress(endpointConfiguration))

    this.ChannelFactory.Credentials.Windows.ClientCredential.UserName = username;
    this.ChannelFactory.Credentials.Windows.ClientCredential.Password = password;
    this.ChannelFactory.Credentials.Windows.ClientCredential.Domain = domain;

    this.Endpoint.Name = endpointConfiguration.ToString();
    ConfigureEndpoint(this.Endpoint, this.ClientCredentials);


private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)

    if ((endpointConfiguration == EndpointConfiguration.ServiceSoap))
    
        System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
        result.MaxBufferSize = int.MaxValue;
        result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
        result.MaxReceivedMessageSize = int.MaxValue;
        result.AllowCookies = true;
        result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
        result.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
        return result;
    
    throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'0\'.", endpointConfiguration));

我已经尝试将 Ntml 和 Windows 作为 ClientCredentialType。

通过在应用程序内硬编码凭据,然后使用正常的 dotnet 运行时运行它来验证它是否有效,我已经验证了在将 api 传输到 docker 容器时身份验证凭据不会被弄乱。最后使用完全相同的已发布应用程序构建 docker 映像并再次运行它。当完全相同的应用程序在 docker 中运行时,它无法进行身份验证。

应用程序的输出是:

The HTTP request is unauthorized with client authentication scheme ‘Negotiate’. The authentication header received from the server was ‘Negotiate, NTLM’.

这与我使用错误凭据时的输出相同。

我想知道这是否与网络与 docker 的工作方式有关,以及 api 是否无法与 WCF 服务协商,因为它是通过 docker 主机桥接的。

如果有人更了解 dotnet 核心中的 docker 或 WCF 消费,可能会有一些见解,这将非常有帮助。

最好的问候,莱纳斯。

【问题讨论】:

【参考方案1】:

对于遇到相同问题的任何人,这是由于在非 Windows 平台上配置 kerberos 的方式。这与 docker per say 无关,而是作为基于 linux 的容器运行。

解决方案是将您的平台切换到 Windows 或在您的平台上正确配置 kerberos 身份验证。这在以下 github 问题中有更详细的讨论:

https://github.com/dotnet/wcf/issues/2641 和 https://github.com/dotnet/corefx/issues/9533

【讨论】:

translate.google.com/…(可能有翻译损失)这是对问题的一些调查和一个hacky解决方法

以上是关于使用外部 WCF 服务时,在 docker 内运行的 Dotnet 核心 Web api 无法进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

带有外部 nginx 和综合的 gitlab docker 注册表

从 Dockerized SpringBoot 到外部 MariaDB 的 JDBC 身份验证失败

docker运行Spring Cloud使用外部IP

docker app 在 https 上服务并连接到外部 rethinkdb

docker端口映射与容器互联

跟我一起学docker--网络