无法使 CustomBinding 在 Mono 中工作
Can't make CustomBinding work in Mono
我写了一个简单的控制台应用程序应该 运行 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 上,因此在域之外,我不得不在代码中设置凭据,而不是通过 'runas' 启动应用程序,后者仅在 Windows 中可用。这是我的代码:
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: Use ClientCredentials to specify a user name for required HTTP Ntlm authentication.
有什么解决方法吗?
P.S。我在 Mono 的 Bugzilla here 中发现了类似的消息,但提供的补丁似乎对 CustomBinding 没有任何作用。
尝试了各种技巧,最终找到了解决方法。解决方法是 - 设置 ClientCredentials.UserName
属性。不幸的是,它是只获取的,所以我不得不使用反射来设置私有字段值。由于它们在本机 .NET 和单声道中不同,代码看起来有点脏,但仍然有效。
这是我的代码:
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);
我写了一个简单的控制台应用程序应该 运行 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 上,因此在域之外,我不得不在代码中设置凭据,而不是通过 'runas' 启动应用程序,后者仅在 Windows 中可用。这是我的代码:
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: Use ClientCredentials to specify a user name for required HTTP Ntlm authentication.
有什么解决方法吗?
P.S。我在 Mono 的 Bugzilla here 中发现了类似的消息,但提供的补丁似乎对 CustomBinding 没有任何作用。
尝试了各种技巧,最终找到了解决方法。解决方法是 - 设置 ClientCredentials.UserName
属性。不幸的是,它是只获取的,所以我不得不使用反射来设置私有字段值。由于它们在本机 .NET 和单声道中不同,代码看起来有点脏,但仍然有效。
这是我的代码:
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);