0

WinForms 应用程序使用 NTLM 身份验证连接到 WCF 服务时遇到问题。

<LongStory-可选>

原始应用程序是我在 2005 年编写的,作为我的第一个 C# 代码。通过小的修改,它运行良好。Web 服务是带有数据集的 asmx。最近有时间升级它,因为:性能问题和客户端上的 Windows 10 升级(Crystal Reports 10.5.37 需要升级到 x64 并且 SAP 站点上没有官方运行时下载)。我使用 WCF、.NET 4.8 重写了它,将 Crystal 替换为库以创建 Excel 文件。在开发人员环境中,新版本运行良好,除了 500 代码。没有考虑 Rest 和 .NET Core(太难解释了;不是技术原因)。

当用户启动新版本时,第一个直接问题是“访问被拒绝”。然后它以管理员身份启动。错误代码:“应用程序无法启动,因为它的并排配置不正确”。然后我试图在事件查看器中获取更多信息但没有成功:没有信息。sxstrace 工具引发访问被拒绝。几天后我明白了:我在包含国家非英语字符的配置文件中做了评论。删除评论后,连接期间出现错误 500。

<\LongStory-可选>

应用程序调用仅返回常量值 1 的验证服务。

错误消息:“响应消息的内容类型 text/html 与绑定的内容类型不匹配 (text/xml; charset=utf-8)。

如果使用自定义编码器,请确保正确实现 IsContentTypeSupported 方法。响应的前 75 个字节是:

该页面无法显示,因为发生了内部服务器错误。” . 未使用 Https。

奇怪的是,在 IE 中打开 .svc 一次后,错误消失了,直到工作站重新启动。这证明客户端和服务器工作正常。同时旧应用程序没有这样的问题。因此,我尝试使用“Web 参考”而不是“服务参考”。看来“网络参考”工作正常。接下来我在客户端尝试了不同的设置。我发现“服务参考”在此更改后有效:client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

使用提琴手工具,我发现消息交换几乎相同,除了最终结果:更改之前我有状态 401/401/500,更改 401/401/200 之后,其他差异是时间和 NTLM base64 值,仅此而已。

我认为这不是解决方案,而只是一种解决方法。您知道如何使用 WCF 正确处理 NTLM 身份验证吗?

我的代码和配置的基本部分:

var client = new ServiceClient();
client.ClientCredentials.Windows.ClientCredential.UserName = Dialog1.textBox1.Text;
client.ClientCredentials.Windows.ClientCredential.Domain = Dialog1.textBox2.Text;
client.ClientCredentials.Windows.ClientCredential.Password = Dialog1.textBox3.Text;
try
{
    i = client.Verify().Status;
} ...         

   

配置:

<system.serviceModel>
  <bindings>
    <basicHttpBinding>
      <binding name="basicEndpoint" sendTimeout="infinite"  >
        <security mode="TransportCredentialOnly">
          <transport clientCredentialType="Ntlm"/>
        </security>
      </binding>
    </basicHttpBinding>
  </bindings>
  <client>
    <endpoint address="http://wro67zt2/AlsbWebServices/WindService/WindService.svc" binding="basicHttpBinding" bindingConfiguration="basicEndpoint" contract="WindService.IService" name="basicEndpoint"/>
  </client>
</system.serviceModel>

我认为服务器端配置是不必要的。它适用于 Web 参考,因此我可以假设这里一切正常。我试过“Windows”而不是“Ntlm”,但问题仍然存在,它在请求/响应消息中将字符串 NTLM 更改为协商,并且消息数量从 3 变为 2(401/500 或 401/200)。

编辑 - 服务器配置:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2"/>
    <globalization culture="en-GB" requestEncoding="utf-8" responseEncoding="utf-8"/>
    <pages controlRenderingCompatibilityVersion="4.0" clientIDMode="AutoID"/>
    <identity impersonate="false" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="basicBinding" >
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows"  realm="XXXXX"/>
            <message clientCredentialType="UserName" algorithmSuite="Default"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>

    <services>
      <service behaviorConfiguration="WindService.Behavior" name="WindLibrary.Service">
        <endpoint 
          address="" 
          binding="basicHttpBinding"
          bindingConfiguration="basicBinding"
          name="basicEndpoint" 
          bindingNamespace="http://XXXXX.com/services/prime/"
          contract="WindLibrary.IService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WindService.Behavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
            <add scheme="http" binding="basicHttpBinding" bindingConfiguration="HttpBinding" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="false"/>
  </system.webServer>
</configuration>
4

0 回答 0