我创建了一个Windows服务,其唯一目的是托管WCF服务。在WCF服务中,我有一个方法,当客户端访问时,读取注册表以获取文件的路径。然后,该方法读取文件的内容并发回内容。
对于存储(并随后读取)文件的业务案例,它不与WCF服务位于同一目录中。尝试访问该文件时,我收到拒绝访问错误。
我认为最简单的解决方案是更改运行Windows服务的帐户。我将帐户更改为LOCAL SERVICE和NETWORK SERVICE。我为这些凭据提供了相关目录的完全安全权限,但仍然无法读取该文件!
我的下一个想法是,因为这些机器在同一个域上,我可以使用模拟来读取文件。我已尝试过该设置,但现在我的客户端无法找到我的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服务不同的凭据下运行。我错了吗?我想我可以试着让“Everyone”访问该文件夹并查看是否有效。
编辑:这是我用来连接服务的客户端代码:
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;
}
答案 0 :(得分:0)
调试您的一个服务电话时,WindowsIdentity.GetCurrent()
会给您什么回复?
我想你在这里有一个冒充问题;如果它不服务帐户,那么你已经为操作/服务启用了模拟(注意,客户端设置不指示模拟,客户端和服务器必须匹配)在这种情况下你有授予您模仿的所有用户的权限。
或您可以表明您想要识别用户,但不能完全模仿。
如果用户 您的服务帐户,则必须仔细检查您尝试为运行该服务的帐户打开的文件的有效权限。