如何在WCF调用的服务端获取用户名和密码?

时间:2011-03-02 16:50:48

标签: .net wcf wcf-security

当我使用以下代码在客户端提供凭据时:

myChannelFactory.Credentials.UserName.UserName = "username";
myChannelFactory.Credentials.UserName.Password = "password";

然后在服务器端,我看到

中提供了这些凭据
operationContext.IncomingMessageHeaders[1]

然而,有没有更方便的方法来获取用户名和密码?我在OperationContext中看到的只是混乱的属性和无类型列表,我无法找到任何表明我可以得到它的地方。

2 个答案:

答案 0 :(得分:3)

您可以使用Current property上的静态ServiceSecurityContext class来获取正在调用的操作的当前ServiceSecurityContext

然后,您可以使用PrimaryIdentity property来获取传入凭据的用户的身份。

但是,它不会(也不应该)公开密码。如果您真的需要密码,那么您必须下拉到消息级别并检查标题,如您所见。

答案 1 :(得分:2)

这完全取决于您使用的绑定,并且没有一般性答案。

例如,如果您使用NetNamedPipeBinding并执行

myChannelFactory.Credentials.UserName.UserName = "username";
myChannelFactory.Credentials.UserName.Password = "password"; 

你浪费时间:客户端绑定对这些数据不起作用,它不会出现在消息中,并且在服务端根本无法访问。

如果绑定配置了指定使用用户名/密码凭据的安全选项,则绑定将仅使用此数据。执行此操作的所有标准绑定都将使用凭据进行身份验证,其结果将通过ServiceSecurityContext作为casperOne指示在服务中显示,并且不包括密码数据。

为了支持身份验证,数据必须携带在邮件头中的某个位置。究竟在哪里以及以何种形式再次依赖于约束力。不要以为您总是会在operationContext.IncomingMessageHeaders[1]中找到它们。

编辑: 您可以构建一个自定义绑定,为您提供所需的内容。

CustomBinding binding = new CustomBinding( ... );
binding.Elements.Insert(1, 
  SecurityBindingElement.CreateUserNameOverTransportBindingElement());

在服务方面,提供UserNamePasswordValidator并配置如下凭据:

serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = 
  System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
servicehost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = 
  new MyUserNamePasswordValidator();

然后,用户名和密码将传递到Validate的{​​{1}}方法。

警告:除非您使用安全传输,否则这不是安全的身份验证机制,因为凭据在邮件头中以明文形式发送。