记录一下我实现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方法

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

 

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 --> 文件-->添加/删除管理单元-->可用的管理单元 下面选择 证书 -->选择计算机账户 --> 选择本地计算机--> 完成

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

 

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

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

4.1. 将basicHttpBinding 修改为wsHttpBinding

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

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

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

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

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

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

添加serviceCredentials

命名为 ServiceBehaviorToUserPassword

双击serviceCredentials进入编辑

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

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

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

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

ServiceBehaviorToUserPassword 配置到 服务的behaviorConfiguration

将wsHttpBindingToUserPassword配置到终结点的bindingConfiguration

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

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

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

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

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

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

让我们看看客户端代码

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);
}
}

 

运行结果

 

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

WCF账户密码认证的更多相关文章

  1. (WCF初体验)WCF的认证和消息保护

    最近做WCF开发,有个需求是在服务端做认证,网上查资料了解到可以用UserName和Password 来做认证,只需要写好配置文件和在服务端写好验证类就行了,但是网上普遍的博文都是需要用证书,而我自己 ...

  2. 以WCF安全认证方式调用通用权限管理系统获取基础信息资料

    在B/S开发中,涉及到获取系统基础资料的问题,因为是在不同平台下的开发,采用了WCF方式获取. 下面是一个调用通用权限管理系统(吉日嘎拉)基础信息资料的一个demo供参考 调用原理图: web.con ...

  3. openvpn 使用账户密码认证

    OpenVPN使用user/passwd完成验证登录 OpenVPN使用user/passwd完成验证登录1,为什么要使用user/passwd?比常规openvpn管理方便,删除用户只需要在pwd. ...

  4. wcf 登录认证 angular 认证重定向

    自定义认证管理器,分为两级:1.登陆认证.2.权限认证.权限主要是用户.角色.角色用户关系.功能(系统资源).角色功能关系,5部分决定用户的权限(视图). 两层认证都通过后,更新session的最新交 ...

  5. WCF权限认证多种方式

    WCF身份验证一般常见的方式有:自定义用户名及密码验证.X509证书验证.ASP.NET成员资格(membership)验证.SOAP Header验证.Windows集成验证.WCF身份验证服务(A ...

  6. WEB/ WCF安全认证

  7. WCF权限控制

       前面写了 WCF账户密码认证, 实现了帐号密码认证, 接下来看看如何对方法的细粒度控制, 本文很大程度参考了 WCF安全之基于自定义声明授权策略, 这篇文章对原理讲得比较清楚, 而我这篇文章呢, ...

  8. WCF的用户名+密码认证方式(转)

    概述 今天在做Master Data Service(后面简称MDS)项目时需要通过WCF来使用MDS的API,从而对MDS的数据进行操作.在这个过程中,遇到了一个棘手的问题,就是在客户端调用Web ...

  9. Expression<Func<T,TResult>>和Func<T,TResult> 与AOP与WCF

    1>>Expression<Func<T,TResult>>和Func<T,TResult>http://www.cnblogs.com/xcsn/p/ ...

随机推荐

  1. 初学Python之字符串操作

    字符串.replace() phone_number='158-8888-8888' hide_number=phone_number.replace(phone_number[:9],'*'*9) ...

  2. IP地址划分

    对于32位的IPV4地址来说,有5中IP地址类型 A类IP地址第一个字节是网络地址,后三个字节是主机地址,且最高位以0开头. 0000001  00000000   00000000 00000001 ...

  3. make[2]: *** No rule to make target `/root/.pyenv/versions/anaconda3-2.4.0/lib/libpython3.5m.so', needed by `evaluation.so'. Stop.

    当出现No rule to make target ,肯定是Makefile有问题. 有的makefile是脚本生成的,你得看脚本的配置文件对不对. 我的是这个脚本生成的.发现是Pythondir的配 ...

  4. Weka使用常见问题

    1.中文乱码 办法:找到RunWeka.ini文件,将Cp1252替换成数据对应的字符集编码,比如utf-8,cp936(简体中文),cp950(繁体中文).

  5. Lambda GroupBy Sum

    DataTable dt = new DataTable(); dt.AsEnumerable().GroupBy(r => r["ShopName"]) .Select(g ...

  6. CSS实现DIV超长截断,并显示...

    DIV显示内容有时会超长,并把页面撑的很难看, 以前的做法是在JS中,或者后台判断其长度,过长就截断, 但由于中英文数字展示的宽度并不一样,截断的长度也就只能取最小值, 展示的效果也不好.利用CSS提 ...

  7. 大毕设-MATLAB-滤波器的实现

    在工程实际中遇到的信号经常伴有噪声,为了消除或减弱噪声,提取有用信号,必须进行滤波,能实现滤波功能的系统称为滤波器.严格地讲,滤波器可以定义为对已知的激励提供规定响应的系统,响应的要求可以在时域或频域 ...

  8. 对于那本--你必须知道的499个C语言问题--总结

    (1)1.3 (2)1.10没看懂 (3)1.11和1.12都讲到了   静态变量和局部变量,那么这两个是啥啊,我不懂: (4)1.13针对那两个字符串定义为啥有问题,不懂 (5)2.8是做什么的 ( ...

  9. transfromjs动画效果

    记得以前facebook做过一款HTML5游戏.开场动画是一块软体类似豆腐的东西一起摇摆.类似的效果如下面的gif所示: facebook当时使用的是createjs下的子项目easeljs和twee ...

  10. wpf 常见死锁方式

    Thread tr0 = new Thread(new ParameterizedThreadStart((obj1) => { lock (aaa) { Thread.Sleep(); thi ...