我正在WPF应用程序和Windows服务抛出WCF之间开发一种“自动连接”模式。 我只想允许受信任的域用户连接到特定的WCF服务,而不需要Windows凭据(该用户已经在Windows会话中登录)。 接下来,该服务将使用户登录到应用程序。
我创建了一个WCF服务,其安全性模式设置为«Transport»,而Transport.ClientCredentialType设置为«Windows»(客户端和服务器上的绑定均相同)。 在同一应用程序中还运行着其他WCF服务,其安全模式设置为“无”。
当我在使用LocalService帐户的域计算机上运行Windows服务,并在使用域用户帐户的另一台计算机上运行客户端时,可以在OperationContext对象的服务器端获取用户Windows身份«DOMAIN \ user» 。 我看到使用了Kerberos,并且我认为可以进行某种形式的模拟,
但是,当我在不认识域用户的工作组计算机(域外)上运行Windows服务时,OperationContext WindowsIdentity设置为“ MACHINE_NAME \ Administrator”(在服务器上创建的本地会话)。 没有错误,服务请求也没有例外,我也不知道为什么。 WindowsIdentity对象的IsAuthenticated属性始终设置为true。
我已经在«消息»的安全模式下进行了测试。
我想知道是否有可能告诉WCF拒绝所有未经真正身份验证的连接吗?
更新: 这里的一些信息可能会有所帮助:
public static TClient Create<TClient, TChannel>(params IContractBehavior[] behaviors)
where TChannel : class
where TClient : ClientBase<TChannel>
{
var typeOfClient = typeof(TClient);
var ctor = typeOfClient.GetConstructor(new[] { _bindingType, _endpointAddressType });
if (ctor == null)
{
throw new Exception($"{typeOfClient} has no constructor taking 2 parameters ({_bindingType},{_endpointAddressType})");
}
var address = getClientBaseEndPointAddress(typeof(TChannel));
var binding = getBinding<TClient>(address.Uri.Scheme);
var clt = (TClient)ctor.Invoke(new object[] { binding, address });
foreach (var behavior in behaviors)
{
clt.ChannelFactory.Endpoint.Contract.Behaviors.Add(behavior);
}
manageDataContractResolver<TClient, TChannel>(clt);
clt.setOperationTimeout(binding.SendTimeout);
return clt;
}
var ret = new NetTcpBinding
{
MaxBufferSize = bc.MessageSize,
MaxBufferPoolSize = bc.MessageSize,
...
};
// Secured or not
if (secured)
{
ret.Name = "Default_Secured_Binding";
ret.Security.Mode = SecurityMode.Transport;
ret.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
}
else
{
ret.Security.Mode = SecurityMode.None;
ret.Name = "Default_Binding";
}
我以为WCF会拒绝任何未经完全身份验证的请求,但我不会收到任何“身份验证错误”。
让我知道是否需要更多信息。
答案 0 :(得分:0)
如果客户端未提供Windows凭据作为客户端Windows凭据,则将使用当前计算机用户的凭据进行身份验证。身份验证的条件是可以将此凭据登录到服务器(Windows用户)
客户端如何调用服务,客户端代理类或ChannelFactory?这是在客户端设置证书的方法。
ServiceReference2.Service1Client client = new ServiceReference2.Service1Client();
//if we don't set up this, The computer user credentials that are currently running the program will be sent to the server.
client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
client.ClientCredentials.Windows.ClientCredential.Password = "123456";
假设服务器端配置在下面,
<system.serviceModel>
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1" bindingConfiguration="mybinding">
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="mybinding">
<security mode="Transport">
<transport clientCredentialType="Windows"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
请张贴完整的服务器配置和客户端配置(system.servicecmodel部分)以供调用,我会尝试查找问题。
随时让我知道是否有什么可以帮助您的。