开发者

Windows Service Hosted WCF Service Getting "Access Denied" When Trying To Read a File

开发者 https://www.devze.com 2023-04-08 07:56 出处:网络
I have created a windows service for the sole purpose of hosting a WCF service.In the WCF service I have a method that when accessed by the client reads the registry for a path to a file.The method th

I have created a windows service for the sole purpose of hosting a WCF service. In the WCF service I have a method that when accessed by the client reads the registry for a path to a file. 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. 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. 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.

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:

<?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 ver开发者_C百科sion="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. 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?

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号