【问题标题】:Windows Service Hosted WCF Service Getting "Access Denied" When Trying To Read a FileWindows 服务托管的 WCF 服务在尝试读取文件时“拒绝访问”
【发布时间】:2011-09-27 15:45:15
【问题描述】:

我创建了一个 Windows 服务,其唯一目的是托管 WCF 服务。在 WCF 服务中,我有一个方法,当客户端访问该方法时,它会读取注册表以获取文件的路径。然后该方法读取文件的内容并将内容发回。

对于正在存储(并随后读取)文件的业务案例,它与 WCF 服务不在同一目录中。尝试访问该文件时,我收到拒绝访问错误。

我认为最简单的解决方案是更改运行 Windows 服务的帐户。我将帐户更改为本地服务和网络服务。我为这些凭据提供了对相关目录的完整安全权限,但仍然无法读取该文件!

我的下一个想法是,因为这些机器位于同一个域中,所以我可以使用模拟来读取文件。我已经尝试过该设置,但现在我的客户端找不到我的 WCF 服务。

我的服务配置有什么问题导致我无法读取文件或访问服务?

这是我在服务中的 App.config:

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="TransportCredWSBinding">
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <services>
      <service name="AMS.CRSS.Service">
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost:8000/CRSS/service"/>
            <add baseAddress="http://localhost:8000/CRSS/service"/>
          </baseAddresses>
        </host>
        <!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/CRSS/service  -->
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransportCredWSBinding" contract="AMS.Core.Services.IService"/>
        <!-- the mex endpoint is exposed at https://localhost:8000/CRSS/service/mex -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False" httpsHelpPageEnabled="true"/>
          <serviceCredentials>
            <clientCertificate>
              <authentication mapClientCertificateToWindowsAccount="true" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

我的想法是 WCF 服务在与其宿主的 Windows 服务不同的凭据下运行。我在这里错了吗?我想我可以尝试让“所有人”访问该文件夹并查看是否可行。

编辑:这是我用来连接服务的客户端代码:

public static CRSSClient GetClientInstance(string clientHost)
    {
        UriBuilder ub = new UriBuilder("https", clientHost, 8000);
        ub.Path = "CRSS/service";

        WSHttpBinding binding = new WSHttpBinding();
        binding.Security.Mode = SecurityMode.Transport;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

        CRSSClient client = new CRSSClient(binding, new EndpointAddress(ub.Uri));
        client.ClientCredentials.Windows.AllowedImpersonationLevel =
            System.Security.Principal.TokenImpersonationLevel.Impersonation;

        return client;
    }

这是我从客户端调用的方法:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string ReadCAMConfig()
    {
        string camConfigText = null;
        string camConfigFileLocation = GetCAMConfigLocationFromReistry();

        EventLog.WriteEntry("CRSS", "Reading CAM File: " + camConfigFileLocation + CAM_FILENAME);

        WindowsIdentity identity = ServiceSecurityContext.Current.WindowsIdentity;
        using (identity.Impersonate())
        {
            try
            {
                if (File.Exists(camConfigFileLocation + CAM_FILENAME))
                {
                    camConfigText = File.ReadAllText(camConfigFileLocation + CAM_FILENAME);
                }
            }
            catch (Exception e)
            {
                EventLog.WriteEntry("CRSS", e.ToOutputString(), EventLogEntryType.Error);
            }
        }

        return camConfigText;
    }

【问题讨论】:

    标签: c# .net wcf windows-services


    【解决方案1】:

    在调试您的一个服务调用时,WindowsIdentity.GetCurrent() 会返回给您什么?

    我想您在这里遇到了假冒问题;如果它不是服务帐户,那么您为操作/服务启用了模拟(注意,客户端设置不指示模拟,客户端和服务器必须匹配)在这种情况下,您必须向所有您模拟的用户授予权限。

    或者你可以只表明你想识别用户,而不是完全模仿。

    如果用户您的服务帐户,那么您必须仔细检查您尝试为运行您的服务的帐户打开的文件的有效权限。

    【讨论】:

    • 事情就是这样,上面的配置我什至无法访问服务。我收到一条错误消息,说我的配置不匹配并且 SOAP 进程不喜欢它并终止连接。我没有确切的错误,因为我又回到使用标准 WsHttpBinding 来调用它而没有安全性。我尝试将“所有人”组添加到文件夹的权限,但我仍然得到:拒绝访问路径“C:\CAMConfig”。在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    • @Mike G:您是否甚至尝试查看当前的 Windows 身份,如答案中所示?
    • 我不确定如何破解服务中的代码。是否需要在服务器实例上安装 VS 远程工具?
    • 当我将绑定设置为使用没有安全性的标准 WsHttpBinding 时,我将用户设为“NT AUTHORITY\\SYSTEM”。我设置了文件权限并能够取回结果。我现在需要解决模拟问题。如果我将 app.config 恢复为原始问题中的状态,我将无法连接到该服务。
    • {"server:8000/CRSS/service 上没有可以接受消息的端点监听。这通常是由不正确的地址或 SOAP 操作引起的。有关更多详细信息,请参阅 InnerException,如果存在。"} - {"无法连接到远程服务器"}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多