C# WCF和自定义身份验证(用户名/密码)
我有通过internet连接到WCF服务的Windows窗体客户端。 WCF服务托管在专用Windows帐户下运行的Windows服务中。 我想通过检查用户名+密码对,根据数据库对客户端进行身份验证 为了避免数百种方法,例如:C# WCF和自定义身份验证(用户名/密码),c#,wcf,authentication,wcf-security,nettcpbinding,C#,Wcf,Authentication,Wcf Security,Nettcpbinding,我有通过internet连接到WCF服务的Windows窗体客户端。 WCF服务托管在专用Windows帐户下运行的Windows服务中。 我想通过检查用户名+密码对,根据数据库对客户端进行身份验证 为了避免数百种方法,例如: public int Add(string User, string Password, int A, int B) 我使用以下指南覆盖了UserNamePasswordValidator类: 我的自定义验证器类与示例匹配 class UsernameAuthenti
public int Add(string User, string Password, int A, int B)
我使用以下指南覆盖了UserNamePasswordValidator
类:
我的自定义验证器类与示例匹配
class UsernameAuthentication : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
//Will be checked against database
var ok = (userName == "Ole") && (password == "Pwd");
if (ok == false)
throw new AuthenticationException("u/p does not match");
}
}
我的服务器配置是:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<system.serviceModel>
<services>
<service name="TestWCFCustomAuth.CalculatorService" behaviorConfiguration="customCred">
<endpoint address="CalcSvc"
binding="netTcpBinding"
bindingConfiguration="secUP"
contract="ServiceInterface.ICalculatorService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="ServiceInterface.ICalculatorService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:81/"/>
<add baseAddress="net.tcp://localhost:82/"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="secUP">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="customCred">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceCredentials>
<!--Service identity + encryption certificate-->
<serviceCertificate findValue="SHKIService" storeLocation="LocalMachine" storeName="Root" x509FindType="FindBySubjectName"/>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="TestWCFCustomAuth.UsernameAuthentication, TestWCFCustomAuth" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
虽然我的代码与指南几乎相同,但我得到一个错误:
System.ServiceModel.Security.SecurityNegotiationException: 'The caller was not authenticated by the service.'
Inner Exception:
FaultException: The request for security token could not be satisfied because authentication failed.
我搜索了几天的答案,并尝试了许多其他配置。我最好的猜测是在幕后发生了其他类型的身份验证?如果是这样的话-我如何禁用它?官方文档中有一个完整的演示,它使用用户名和密码验证,还具有证书验证。您只需按照教程中的步骤即可成功运行。您可以参考。我缺少的步骤如下:
CurrentUser\Trusted People
store中拥有证书(即使客户端和服务器在同一台计算机上运行)。因此,我使用上一步中的mmc工具将没有私钥的证书导出到一个文件中,然后将该文件中的证书导入CurrentUser\Trusted People
store。我想我必须将这个文件包含到我客户的安装包中
makecert.exe
工具来创建证书,正如@Theobald Du提供的msdn参考中所建议的那样
这些命令是:
makecert.exe-sr LocalMachine-ss MY-a sha1-n CN=谢谢!这与证书的创建方式或我没有将其复制到“CurrentUser/Trusted People”存储中有关。稍后我将发布更多详细信息,以向任何有类似问题的人说明。另外,wsHttpBinding和netTcpBinding都可以工作,我们现在可以选择了!
var client = new CalculatorServiceClient("NetTcpBinding_ICalculatorService");
client.ClientCredentials.UserName.UserName = "Ole";
client.ClientCredentials.UserName.Password = "Pwd";
var res = client.Add(1, 2);
Console.WriteLine("Result: {0}", res);
System.ServiceModel.Security.SecurityNegotiationException: 'The caller was not authenticated by the service.'
Inner Exception:
FaultException: The request for security token could not be satisfied because authentication failed.