简体   繁体   English

Windows Service托管的WCF服务在尝试读取文件时获得“访问被拒绝”

[英]Windows Service Hosted WCF Service Getting “Access Denied” When Trying To Read a File

I have created a windows service for the sole purpose of hosting a WCF service. 我创建Windows服务的唯一目的是托管WCF服务。 In the WCF service I have a method that when accessed by the client reads the registry for a path to a file. 在WCF服务中,我有一个方法,当客户端访问该方法时,它会读取注册表以获取文件的路径。 The method then reads the contents of a file and sends back the contents. 然后,该方法读取文件的内容并将其发送回。

Do to the business case where the file is being stored (and subsequently read) it is not located within the same directory as the WCF service. 对于要存储(并随后读取)文件的业务案例,请与WCF服务不在同一目录中。 When trying to access the file I get an access denied error. 尝试访问文件时,出现访问被拒绝错误。

I thought that the easiest solution was to change the account under which my windows service was running. 我认为最简单的解决方案是更改运行Windows服务的帐户。 I changed the account to LOCAL SERVICE and NETWORK SERVICE. 我将帐户更改为本地服务和网络服务。 I provided full security permissions to the directory in question for those credentials and was still unable to read the file! 我为有关这些凭证的目录提供了完整的安全权限,但仍然无法读取该文件!

My next thought was since these machines are on the same domain that I could use impersonation to read the file. 我的下一个想法是,因为这些计算机位于可以使用模拟读取文件的同一域中。 I have tried that setup, but now my client can't find my WCF service. 我已经尝试了该设置,但是现在我的客户端找不到我的WCF服务。

What is wrong with my configuration for my service that is preventing me from either reading the file or accessing the service? 我的服务配置出现了什么问题,导致我无法读取文件或访问该服务?

Here is my App.config from the service: 这是来自服务的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>

My thought is that the WCF service is running under different credentials than the Windows Service which is its host. 我的想法是,WCF服务在与作为其宿主的Windows服务不同的凭据下运行。 Am I wrong here? 我在这里错了吗? I suppose I could try giving "Everyone" access to the folder and seeing if that works. 我想我可以尝试授予“所有人”访问该文件夹的权限,看看是否可行。

EDIT: Here is the client code that I am using to connect to the service: 编辑:这是我用来连接到服务的客户端代码:

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;
    }

Here is the method which I am invoking from the 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;
    }

When debugging one of your service calls, what does WindowsIdentity.GetCurrent() return to you? 在调试您的服务调用之一时, WindowsIdentity.GetCurrent()返回给您什么?

I imagine you have an impersonation issue here; 我想您在这里遇到假冒问题; if it's not the service account, then you have impersonation enabled for the operation/service (note, the client side settings don't dictate impersonation, client & server have to match) in which case you have to give permission to all of the users that you are impersonating. 如果不是服务帐户,那么您已为操作/服务启用了模拟(请注意,客户端设置并不要求模拟,客户端和服务器必须匹配),在这种情况下,您必须授予所有用户权限您正在冒充。

Or you could just indicate that you want to identify the user, but not exactly impersonate. 或者,您可以只表明您要标识用户,而不能完全模拟。

If the user is your service account, then you have to double-check the effective permissions on the files you are trying to open for the account your service is running under. 如果用户您的服务帐户,那么您必须仔细检查您要为其运行服务的帐户所尝试打开的文件的有效权限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM