如何在 WCF 中添加用户/通行证身份验证 [英] How to add user/pass authentication in WCF

查看:42
本文介绍了如何在 WCF 中添加用户/通行证身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为我的 WCF 应用程序服务添加一些安全性.我想出了如何添加用户名/密码身份验证:

<行为><服务行为><行为名称=我的行为"><serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="false"/><serviceCredentials><userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Changer.Service.Validation.ServiceAuthenticator, Changer.Service"/></serviceCredentials></行为></serviceBehaviors></行为><绑定><wsHttpBinding><绑定名称="MyBinding"><安全模式="TransportWithMessageCredential"><message clientCredentialType="UserName"/></安全></binding></wsHttpBinding></绑定><服务><服务名称="Changer.Service.Request.RequestService" behaviorConfiguration="MyBehavior"><endpoint address="/" binding="wsHttpBinding" contract="Changer.Service.Request.IRequestService" bindingConfiguration="MyBinding"/></服务></服务></system.serviceModel>

这是我的自定义数据验证:

公共类 ServiceAuthenticator : UserNamePasswordValidator{公共覆盖无效验证(字符串用户名,字符串密码){//检查用户名和密码如果(用户名!= Authentication.Providers.Service.PasswordChanger.UserName ||密码 != Authentication.Providers.Service.PasswordChanger.Password){throw new System.IdentityModel.Tokens.SecurityTokenException("未知用户名或密码.");}}}

不幸的是,我收到错误消息,因为我没有有效的证书.我尝试按照本教程进行操作:

然后我们在IIS网站绑定模块中添加https绑定,这样WCF服务就可以成功托管了.
自定义认证类.根据实际情况,在上面的配置文件中配置这个认证类.

 内部类 CustUserNamePasswordVal : UserNamePasswordValidator{公共覆盖无效验证(字符串用户名,字符串密码){如果(用户名!=杰克"||密码!=123456"){throw new Exception("用户名/密码不正确");}}}<serviceCredentials><userNameAuthentication customUserNamePasswordValidatorType="WcfService1.CustUserNamePasswordVal,WcfService1" userNamePasswordValidationMode="Custom"/></serviceCredentials>

客户.

//用于验证服务器证书.ServicePointManager.ServerCertificateValidationCallback += 委托{返回真;};ServiceReference2.Service1Client 客户端 = new ServiceReference2.Service1Client();client.ClientCredentials.UserName.UserName = "jack";client.ClientCredentials.UserName.Password = "123456";

如果我们使用消息安全,我们可以通过下面的代码设置证书.(根据实际情况配置您的实际证书)

<serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" findValue="869f82bd848519ff8f35cbb6b667b34274c8dcfe"/><userNameAuthentication customUserNamePasswordValidatorType="WcfService1.CustUserNamePasswordVal,WcfService1" userNamePasswordValidationMode="Custom"/></serviceCredentials>

请参考以下链接.
WCF-TransportWithMessageCredential HTTP 请求未经客户端授权身份验证方案匿名"
WCF 用户名 &使用 wshttpbinding 无效的密码验证
如果有什么我可以帮忙的,请随时告诉我.

I want to add some security to my WCF application service. I figured out how to add username/password authentication:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="MyBehavior">
        <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Changer.Service.Validation.ServiceAuthenticator, Changer.Service"/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name="MyBinding">
        <security mode="TransportWithMessageCredential">
          <message clientCredentialType="UserName" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <services>
    <service name="Changer.Service.Request.RequestService" behaviorConfiguration="MyBehavior">
      <endpoint address="/" binding="wsHttpBinding" contract="Changer.Service.Request.IRequestService" bindingConfiguration="MyBinding" />
    </service>
  </services>
</system.serviceModel>

This is my custom data validation:

public class ServiceAuthenticator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // Check the user name and password
        if (userName != Authentication.Providers.Service.PasswordChanger.UserName || 
            password != Authentication.Providers.Service.PasswordChanger.Password)
        {
            throw new System.IdentityModel.Tokens.SecurityTokenException("Unknown username or password.");
        }
    }
}

Unfortunelly I am getting error which is because I have no valid certificate. I tried following this tutorial: https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-an-iis-hosted-wcf-service-with-ssl

But without success. It says, that certificate hosts is not matching site url I am visiting. On client side I am getting error:

Could not establish trust relationship for the SSL/TLS secure channel with authority 'foo'. The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. The remote certificate is invalid according to the validation procedure

I can solve this by adding to my client app:

System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };

Which is basically not solving my problem.. What can I do with that? I just want to have simple user/pass authentication.

I decided to get rid off SSL, then my code changed to:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="MyBehavior">
        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
        <serviceDebug includeExceptionDetailInFaults="true" />
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="PasswordChanger.Service.Validation.ServiceAuthenticator, PasswordChanger.Service"/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name ="NewBinding">
        <security mode="Message">
          <message clientCredentialType="UserName"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <protocolMapping>
    <add binding="basicHttpsBinding" scheme="https" />
  </protocolMapping> 
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>

And after that I got this error:

Error: Cannot obtain Metadata from http://localhost:53705/R.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at www.WS-Metadata Exchange Error URI: http://localhost:53705/R.svc Metadata contains a reference that cannot be resolved: 'http://localhost:53705/R.svc'. Content Type application/soap+xml; charset=utf-8 was not supported by service http://localhost:53705/R.svc. The client and service bindings may be mismatched. The remote server returned an error: (415) Cannot process the message because the content type 'application/soap+xml; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'..HTTP GET Error URI: http://localhost:53705/R.svc The HTML document does not contain Web service discovery information.

So I decided to add services tag to my web.config next to bindings

<services>
  <service name="PasswordChanger.Service.Request.RequestService" behaviorConfiguration="MyBehavior">
    <endpoint address="/" binding="wsHttpBinding" contract="PasswordChanger.Service.Request.IRequestService" bindingConfiguration="NewBinding" />
  </service>

And I got another error: The service certificate is not provided. Specify a service certificate in ServiceCredentials.

解决方案

Whether we use the message security or transport layer security mode, we all need to provide a certificate to ensure that the username/password authentication mode is secure. I have made an example related transport security mode. we need provide a certificate to ensure that the service is hosted successfully.

    <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceCredentials>
            <userNameAuthentication customUserNamePasswordValidatorType="WcfService1.CustUserNamePasswordVal,WcfService1" userNamePasswordValidationMode="Custom"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding>
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

If we don’t have a certificate, we could generate a self-signed certificate by using IIS Server Certificate Tool.


then we add https binding in the IIS website binding module so that the WCF service is hosted successfully.
Custom Authentication class. Based on the actual situation, configure this authentication class in the configuration file above.

    internal class CustUserNamePasswordVal : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (userName != "jack" || password != "123456")
            {
                throw new Exception("Username/Password is not correct");
            }
        }
}
  <serviceCredentials>
            <userNameAuthentication customUserNamePasswordValidatorType="WcfService1.CustUserNamePasswordVal,WcfService1" userNamePasswordValidationMode="Custom"/>
          </serviceCredentials>

Client.

//for validating the server certificate. 
ServicePointManager.ServerCertificateValidationCallback += delegate
              {
                  return true;
              };
            ServiceReference2.Service1Client client = new ServiceReference2.Service1Client();
            client.ClientCredentials.UserName.UserName = "jack";
            client.ClientCredentials.UserName.Password = "123456";

if we use the message security, we could set up the certificate by the following code.( Configure your actual certificate according to the actual situation)

<serviceCredentials>
            <serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" findValue="869f82bd848519ff8f35cbb6b667b34274c8dcfe"/>
            <userNameAuthentication customUserNamePasswordValidatorType="WcfService1.CustUserNamePasswordVal,WcfService1" userNamePasswordValidationMode="Custom"/>
          </serviceCredentials>

Refer to the below link.
WCF-TransportWithMessageCredential The HTTP request is unauthorized with client authentication scheme 'Anonymous'
WCF UserName & Password validation using wshttpbinding notworking
Feel free to let me know if there is anything I can help with.

这篇关于如何在 WCF 中添加用户/通行证身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆