可以';t使CustomBinding在Mono中工作

本文关键字:Mono 工作 CustomBinding 可以 | 更新日期: 2023-09-27 18:20:37

我写了一个简单的控制台应用程序,应该在Linux上运行。

该应用程序使用预编译的dll(我想它运行得很好),除了一件事:远程服务器使用自定义绑定配置,无法重新配置。配置如下:

<bindings>
  <customBinding>
    <binding name="myBinding">
      <binaryMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16">
        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="163840000" maxBytesPerRead="4096"
                      maxNameTableCharCount="16384" />
      </binaryMessageEncoding>
      <httpsTransport manualAddressing="false" maxBufferPoolSize="524288" maxReceivedMessageSize="655360000"
                      allowCookies="false" authenticationScheme="Ntlm" bypassProxyOnLocal="false"
                      decompressionEnabled="true" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true"
                      maxBufferSize="655360000" proxyAuthenticationScheme="Ntlm" realm="" transferMode="Buffered"
                      unsafeConnectionNtlmAuthentication="true" useDefaultWebProxy="true">
      </httpsTransport>
    </binding>
  </customBinding>
</bindings>
<client>
  <endpoint address="REMOTE_LINK_HERE" binding="customBinding"
            bindingConfiguration="myBinding" contract="CONTRACT_NAME"
            name="myBinding">
  </endpoint>
</client>

因此,服务器使用Ntlm进行身份验证。由于该应用程序必须在Linux上运行,因此在域之外,我不得不在代码中设置凭据,而不是通过仅在Windows中可用的"runas"启动应用程序。这是我的代码:

var client = new ...;
if (client.ClientCredentials != null)
{
    client.ClientCredentials.Windows.ClientCredential
                    = new NetworkCredential(options.UserName, options.Password, options.Domain);
    client.ClientCredentials.Windows.AllowedImpersonationLevel
                    = TokenImpersonationLevel.Identification;
}

问题是,我的应用程序在本机.NET CLR上的Windows中运行得很好。使用xbuild编译并在Linux上启动后,我收到错误消息:

System.InvalidOperationException:使用ClientCredentials为所需的HTTP Ntlm身份验证指定用户名。

对此有什么变通办法吗?

附言:我在Mono的Bugzilla中发现了类似的消息,但提供的补丁似乎与CustomBinding无关。

可以';t使CustomBinding在Mono中工作

finnaly尝试了各种技巧,找到了一个解决方法。解决方法是-设置ClientCredentials.UserName属性。不幸的是,它是get only,所以我不得不使用反射来设置私有字段值。由于它们在原生.NET和mono中有所不同,所以代码看起来有点脏,但仍然有效。

这是我的代码:

var credentials = client.ClientCredentials.UserName;
var userNameProperty = credentials.GetType()
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
    .FirstOrDefault(p => p.Name.ToLower() == "username");
if (userNameProperty != null)
    userNameProperty.SetValue(credentials, Options.UserName);
var passwordProperty = credentials.GetType()
    .GetField("password", BindingFlags.NonPublic | BindingFlags.Instance);
if (passwordProperty != null)
    passwordProperty.SetValue(credentials, Options.Password);