用户名经过自定义验证。这是由 FarmService 程序集中的 FarmService.Authentication.DistributorValidator 类完成的。该类继承自 WCF 类 UserNamePasswordValidator 并重写 Validate 方法。
public class DistributorValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Username and password required");
var repository = new DistributorRepository();
if (! repository.IsKnownDistributor(userName, password))
throw new FaultException(string.Format("Wrong username ({0}) or password ", userName));
}
}
除了一个绝对必要的细节。要使用户名密码身份验证正常工作,托管服务的服务器需要 X509 证书。否则所有服务调用都会失败。此证书在服务行为中指定。
<serviceCertificate findValue="Farm" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
首先你需要一个证书。您可以创建自己的,而不是购买一个(绑定到特定的服务器地址,因此对于测试目的同样无用)。 .net 框架附带了生成这些工具的工具,并且有几个教程如何使用这些工具。 selfcert 是一种更简单的工具,只需单击几下即可完成整个过程。
他们在这里没有告诉你的是,你必须以管理员身份运行该工具,否则它将非常不优雅地崩溃。该工具还不清楚在哪里存储生成的证书。默认情况下,它存储在 MyStore 中。在验证证书时,它的可信度取决于它的存储位置。当商店不受信任时,将启动验证链。您也可以直接将证书存储在受信任的存储中,而不是设置证书链。
要使用此服务,请在客户端中添加服务引用。服务配置中的 mexHttpBinding 可以在没有任何凭据的情况下从服务中读取所有元数据。
建立与客户端的连接需要一些麻烦。同样,并非所有这些设置在默认情况下都是明确的。
var endPoint = new EndpointAddress(new Uri(Farm.FarmUrl), EndpointIdentity.CreateDnsIdentity("Farm"));
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
var result = new CustomerDeskOperationsClient(binding, endPoint);
result.ClientCredentials.UserName.UserName = Farm.FarmUserName;
result.ClientCredentials.UserName.Password = Farm.FarmPassword;
详情可参考A simple WCF service with username password authentication
希望对您有所帮助!