zoukankan      html  css  js  c++  java
  • WCF账户密码认证

    记录一下我实现WCF用户认证与权限控制的实现方法, 也让其他网友少走一些弯路. 内容写得非常小白(因为我也是小白嘛), 比较详细, 方便WCF知识基础薄的朋友

    主要分为下面几个步骤

    1. 作为例子, 创建最简单的WCF服务
    2. 生成X.509证书, 并导入到服务端和客户端
    3. 为服务提供帐号密码验证程序, 并配置App.config
    4. 生成客户端并配置其App.config

    这里要解释一下为什么要用X509证书: 因为我们需要X509证书这种非对称密钥技术来实现WCF在Message传递过程中的加密和解密,要不然用户名和密码就得在网络上明文传递!详细说明就是客户端把用户名和密码用公钥加密后传递给服务器端,服务器端再用自己的私钥来解密,然后传递给相应的验证程序来实现身份验证

    0. 开发环境

    Win7 64bit

    VS2010 或者更高

    .Net Framework 4

    1. 新建服务端

    创建一个最基本的WCF服务, 我这里命名为 WCF_UserPassword, 接下来我们将直接使用里面的GetData方法

    image

    直接按F5, 你就可以使用WCF测试服务端, 看到服务已经可以使用了

    image

    2. 生成X.509证书, 并导入到服务端和客户端

    生成X509证书需要用到makecert.exe, 只要安装了Visual Studio, 就可以在C盘找到, 为了操作方便, 将它拷贝到 D:Cert; 安装证书需要用到CertMgr.exe, 所以也拷贝进来吧, 这两个exe都有32位版本和64位版本, 请拷贝与自己系统一致的版本; 最后还要用到pvk2pfx.exe, 这个只有32位版本(VS2013 又有64位版本)

    2.1. 服务端和客户端 在同一台电脑上的情况

    在服务端生成X.509证书

    打开CMD, 切换到D:Cert\, 运行下面这个命令

    makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=MyServerCert -sky exchange -pe

    这个命令的意思就是创建一个测试的X509证书,这个证书放在存储位置为"Localmachine"(本地计算机)的"My"(个人)这个证书文件夹下,证书主题名字叫"MyServerCert"

    你可以通过mmc查看是否安装成功, 运行mmc --> 文件-->添加/删除管理单元-->可用的管理单元 下面选择 证书 -->选择计算机账户 --> 选择本地计算机--> 完成

    image

    2.2. 将服务器证书公匙安装到客户端的 受信任人的存储区中

    certmgr.exe -add -r LocalMachine -s My -c -n MyServerCert -r LocalMachine -s TrustedPeople

    因为客户端系统不隐式信任 Makecert.exe 生成的证书,所以需要执行此步骤。如果您已经拥有一个证书,该证书来源于客户端的受信任根证书(例如由 Microsoft 颁发的证书),则不需要执行使用服务器证书填充客户端证书存储区这一步骤。

    2.3. 服务端和客户端 在不同电脑上 的情况(这个例子里没有用到这节内容)

    生成密匙

    makecert -r -pe -sky exchange -n "CN=MyServerCert" MyServerCertPublicKey.cer -sv MyServerCertPrivateKey.pvk
    pvk2pfx.exe -pvk MyServerCertPrivateKey.pvk -spc MyServerCertPublicKey.cer -pfx MyServerCertExchange.pfx

    你将得到

    MyServerCertExchange.pfx     //密匙交换文件
    MyServerCertPrivateKey.pvk    //私匙
    MyServerCertPublicKey.cer     //公匙

    在服务端: 将MyServerCertExchange.pfx导入到 本地计算机证书 -->个人--> 证书

    CMD: certmgr.exe -add -c MyServerCertExchange.pfx -r LocalMachine -s my

    在客户端: 将MyServerCertPublicKey.cer 导入到 本地计算机证书 --> 受信任人-->证书

    CMD: certmgr.exe -add -c MyServerCertPublicKey.cer -r LocalMachine -s TrustedPeople

    3. 添加验证程序

    添加一个 继承自System.IdentityModel.Selectors.UserNamePasswordValidator 的MyCustomValidator 类, 重写里面的Validate方法来实现用户名密码认证逻辑

    using System.IdentityModel.Selectors;
    using System.IdentityModel.Tokens;
    using System.ServiceModel;
    
    namespace WCF_UserPassword
    {
        public class MyCustomValidator : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                //这里仅简单演示一下, 实际工作中应该是使用 数据库查询 
                if (userName == "admin" && password == "admin") return;
                if (userName == "admin2" && password == "admin2") return;
                
                throw new FaultException("用户名或者密码错误!");
                //throw new SecurityTokenException("用户名或者密码错误!"); //这种异常, 客户端将不能得到 错误信息
            }
        }
    }

    这需要添加引用 System.IdentityModel.dll

    image

    4. 配置服务端App.config, 主要包括以下内容

    1. 将basicHttpBinding 修改为wsHttpBinding
    2. 创建一个新wsHttpBinding的配置
    3. 服务行为中添加一个serviceCredentials

    4.1. 将basicHttpBinding 修改为wsHttpBinding

    image

    4.2. 创建一个新wsHttpBinding的配置, 命名为wsHttpBindingToUserPassword

    image

    这个的设置改动只有一个, 切换至 安全性Tab, 把MessageClientCredentialType 从 Windows 改为 UserName

    image

    在配置文件App.config 中显示的是

    <binding name="wsHttpBindingToUserPassword">
      <security>
        <message clientCredentialType="UserName" />
      </security>
    </binding>

    4.3. 服务行为中添加一个serviceCredentials(最核心的设置)

    高级-->服务行为-->右键 空名称, 选择: 添加服务行为元素扩展

    image

    添加serviceCredentials

    image

    命名为 ServiceBehaviorToUserPassword

    image

    双击serviceCredentials进入编辑

    image

    将userNamePasswordValidationMode 改为 Custom, 将customUserNamePasswordValidatorType填入"WCF_UserPassword.MyCustomValidator,WCF_UserPassword"

    image

    展开serviceCredentials就可以看到serviceCertificate, 将FindValue填入MyServerCert, 将X509FindType从FindBySubjectDistinguishedName改为FindBySubjectName

    image

    默认情况下, 客户端需要使用信任链对证书进行验证, 但由于导入到客户端的证书是我们自己创建的, 不具有可验证的信任链, 所以需要继续修改clientCertificate, CertificateValidationMode改为PeerTrust(只有证书在TrustedPeople 就完全信任), 将FindValue填入MyServerCert, StoreLocation改为LocalMachine, StoreName改为TrustedPeople, 将X509FindType从FindBySubjectDistinguishedName改为FindBySubjectName

    image

    4.4. 将以上添加的节点配置到服务中去

    ServiceBehaviorToUserPassword 配置到 服务的behaviorConfiguration

    image

    将wsHttpBindingToUserPassword配置到终结点的bindingConfiguration

    image

    4.5. 将终结点的Dns从默认的localhost改为MyServerCert

    image

    5. 现在你可以运行服务端了, 调用GetData方法将弹出 "指定用户名" 的错误, 这表示我们服务端的配置起效了

    image

    6. 重新打开一个Visual Studio, 新建一个Console控制台程序, 命名为WCF_Client

    运行服务端, 以方便客户端获取服务信息, 服务地址一般都很长, 还是直接复制服务地址吧

    image

    控制台程序的引用上添加服务引用

    image

    就直接使用默认的命名ServiceReference1吧

    image

    让我们看看客户端代码

    static void Main(string[] args)
    {
        var proxy = new ServiceReference1.Service1Client();
        proxy.ClientCredentials.UserName.UserName = "admin";
        proxy.ClientCredentials.UserName.Password = "admin";
     
        try
        {
            Console.WriteLine(proxy.GetData(2));
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    运行结果

    image

    源代码 WCF_Course账户密码认证.rar, 运行程序, 至少需要你完整完成第二步 "生成X.509证书, 并导入到服务端和客户端"

  • 相关阅读:
    转 MySQL 日期类型详解
    ServiceStack.OrmLite 笔记9 -code first 必须的代码优先
    ServiceStack.OrmLite 笔记8 -还是有用的姿势
    ServiceStack.OrmLite 学习笔记7-复杂点的使用1
    ServiceStack.OrmLite 6 学习笔记 查
    ServiceStack.OrmLite 笔记5 改
    ServiceStack.OrmLite 笔记4 删
    ServiceStack.OrmLite 学习笔记3 建表
    ServiceStack.OrmLite 笔记2 -增
    ServiceStack.OrmLite 笔记
  • 原文地址:https://www.cnblogs.com/zhouandke/p/5823930.html
Copyright © 2011-2022 走看看