zoukankan      html  css  js  c++  java
  • [转贴][WCF Security] 4. 用户名/密码身份验证

    原文:http://www.rainsts.net/article.asp?id=475

    X.509 比较适合验证 "客户机" 的身份,而另外一方面,我们可能需要针对具体的 "用户" 进行验证。本文将记述基于 "用户名/密码" 方式的身份验证开发步骤。

    1. 服务器数字证书

    我们同样需要为服务器准备一个数字证书。

    D:\>makecert -r -pe -n "CN=MyServer" -ss My -sky exchange

    2. 创建服务
    [ServiceContract]
    public interface IService
    {
      [OperationContract]
      string Test();
    }

    public class MyService : IService
    {
      public string Test()
      {
        return "Server:" + DateTime.Now.ToString();
      }
    }

    public class WcfTest
    {
      public static void Test()
      {
        ServiceHost host = new ServiceHost(typeof(MyService));
        host.Open();
      }
    }


    我们通过继承 UserNamePasswordValidator 来创建一个自定义验证器。
    public class MyUserNamePasswordValidator : UserNamePasswordValidator
    {
      public override void Validate(string userName, string password)
      {
        if (userName != "user" || password != "pwd")
        {
          throw new SecurityTokenException("Unknown Username or Password");
        }
      }
    }

    接下来创建服务器配置文件,我们使用 WsHttpBinding,采取 Message 安全模式。其他的设置还包括 certificateValidationMode、userNamePasswordValidationMode、customUserNamePasswordValidatorType 等。
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="NewBehavior">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="true" />
              <serviceCredentials>
                <clientCertificate>
                  <authentication certificateValidationMode="None" />
                </clientCertificate>
                <serviceCertificate findValue="MyServer" storeLocation="CurrentUser"
                  x509FindType="FindBySubjectName" />
                <userNameAuthentication userNamePasswordValidationMode="Custom"
                  customUserNamePasswordValidatorType=
                    "Learn.Library.WCF.MyUserNamePasswordValidator, Learn.Library.WCF" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <bindings>
          <wsHttpBinding>
            <binding name="Binding1">
              <security mode="Message">
                <message clientCredentialType="UserName" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
        <services>
          <service behaviorConfiguration="NewBehavior" name="Learn.Library.WCF.MyService">
            <endpoint address="service" binding="wsHttpBinding" bindingConfiguration="Binding1"
              name="username" contract="Learn.Library.WCF.IService" />
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:8080" />
              </baseAddresses>
            </host>
          </service>
        </services>
      </system.serviceModel>
    </configuration>


    3. 创建客户端

    启动服务器后,创建客户端代理文件。注意自动生成的客户端配置文件中包含了服务器数字证书的相关信息。
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <bindings>
          <wsHttpBinding>
            <binding name="username">
              <security mode="Message">
                <message clientCredentialType="UserName" negotiateServiceCredential="true"
                  algorithmSuite="Default" establishSecurityContext="true" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
        <client>
          <endpoint address="http://localhost:8080/service" binding="wsHttpBinding"
            bindingConfiguration="username" contract="ConsoleApplication1.localhost.IService"
            name="username">
            <identity>
              <certificate encodedValue="AwAA...IgFHqYA==" />
            </identity>
          </endpoint>
        </client>
      </system.serviceModel>
    </configuration>

    开始调用服务,注意将 CertificateValidationMode 设置为 None,当然也可以写到配置文件中。
    using (ServiceClient client = new ServiceClient())
    {
      client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
        X509CertificateValidationMode.None;

      client.ClientCredentials.UserName.UserName = "user";
      client.ClientCredentials.UserName.Password = "pwd";

      Console.WriteLine(client.Test());
    }

    OK! 测试通过! [lol]
    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    [LintCode] Flatten Nested List Iterator 压平嵌套链表迭代器
    [LintCode] Reverse Pairs 翻转对
    [CareerCup] 17.9 Word Frequency in a Book 书中单词频率
    [CareerCup] 17.8 Contiguous Sequence with Largest Sum 连续子序列之和最大
    [CareerCup] 17.7 English Phrase Describe Integer 英文单词表示数字
    [LeetCode] Reverse Vowels of a String 翻转字符串中的元音字母
    [CareerCup] 17.6 Sort Array 排列数组
    [LeetCode] 344. Reverse String 翻转字符串
    [CareerCup] 17.5 Game of Master Mind 猜字游戏
    [CareerCup] 17.4 Maximum of Two Numbers 两数中的较大值
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1271163.html
Copyright © 2011-2022 走看看