我想从控制台应用程序发布WCF服务。出于安全考虑,我想通过SSL进行通信,因此我创建了一个自签名证书。对于身份验证,我编写了自己的UserNamePasswordValidator。不幸的是,这不起作用
到目前为止,这是我的代码:
服务器
public class Program
{
public static void Main()
{
var baseAddress = new Uri("https://localhost:8080/SelfHostedUsernamePasswordService");
using (var host = new ServiceHost(typeof(SelfHostedUsernamePasswordService), baseAddress))
{
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
var endpoint = host.AddServiceEndpoint(typeof(ISelfHostedUsernamePasswordService), binding, baseAddress);
var cf = new ChannelFactory<ISelfHostedUsernamePasswordService>(binding, endpoint.Address);
cf.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
"0000000000000000000000000000000000000000");
var metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpsGetEnabled = true;
metadataBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(metadataBehavior);
var credentialBehavior = new ServiceCredentials();
credentialBehavior.UserNameAuthentication.CustomUserNamePasswordValidator = new UsernamePasswordValidator();
credentialBehavior.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
host.Description.Behaviors.Add(credentialBehavior);
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
public class UsernamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (!string.Equals(userName, "admin", StringComparison.OrdinalIgnoreCase) ||
!string.Equals(password, "password", StringComparison.Ordinal))
{
Console.WriteLine("Validation failed.");
throw new SecurityTokenException("Validation failed.");
}
Console.WriteLine("Validation successful.");
}
}
客户端
class Program
{
static void Main()
{
using (var client = new SelfHostedUsernamePasswordServiceClient())
{
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "password";
var result = client.GetData(12345);
Console.WriteLine("Result from service: {0}", result);
client.Close();
}
}
}
使用此代码,我收到MessageSecurityException(无法找到'System.IdentityModel.Tokens.UserNameSecurityToken'令牌类型的令牌身份验证器)。但我想创建一个TokenAuthenticator,我走错了路......
顺便说一句,从不调用UsernamePasswordValidator。
答案 0 :(得分:4)
好的,明白了。
我必须将Transport CredentialType设置为&#39; Certificate&#39;和Message CredentialType到&#39; UserName&#39;。在双方。
这是工作代码:
服务器强>
public class Program
{
public static void Main()
{
var baseAddress = new Uri("https://localhost:8080/SelfHostedUsernamePasswordService");
using (var host = new ServiceHost(typeof(SelfHostedUsernamePasswordService), baseAddress))
{
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
var endpoint = host.AddServiceEndpoint(typeof(ISelfHostedUsernamePasswordService), binding, baseAddress);
var cf = new ChannelFactory<ISelfHostedUsernamePasswordService>(binding, endpoint.Address);
cf.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
"0000000000000000000000000000000000000000");
var credentialBehavior = new ServiceCredentials();
credentialBehavior.UserNameAuthentication.CustomUserNamePasswordValidator = new UsernamePasswordValidator();
credentialBehavior.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
credentialBehavior.IssuedTokenAuthentication.AllowUntrustedRsaIssuers = true;
host.Description.Behaviors.Add(credentialBehavior);
var metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpsGetEnabled = true;
metadataBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(metadataBehavior);
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
public class UsernamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (!string.Equals(userName, "admin", StringComparison.OrdinalIgnoreCase) ||
!string.Equals(password, "password", StringComparison.Ordinal))
{
Console.WriteLine("Validation failed.");
throw new SecurityTokenException("Validation failed.");
}
Console.WriteLine("Validation successful.");
}
}
<强>客户端强>
class Program
{
static void Main()
{
var remoteAddress = new EndpointAddress(new Uri("https://localhost:8080/SelfHostedUsernamePasswordService"));
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
using (var client = new SelfHostedUsernamePasswordServiceClient(binding, remoteAddress))
{
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "password";
var result = client.GetData(12345);
Console.WriteLine("Got result from service: {0}", result);
Console.ReadLine();
client.Close();
}
}
}