WCF作为.net三大组件之一,伟大之处不用多说,但是其加密配置对于我这样的萌新来说还是颇有难度,因此将几天来的研究成果共享出来,与各位共勉~

  首先声明我的开发环境,Win10创意者更新 + Visual Studio 2015 update3 + .Net 4.5 + iis10

  一、创建X.509证书

    1、创建证书

    可通过PowerShell或者makecert工具两种方式,个人建议使用参考资料更多后者,但最新的Windows和VS都不带makecert,所以需要的话可以到文章结尾处下载。

    使用CMD运行: 

makecert -sr CurrentUser -ss My -n CN=HelloServiceClient -sky exchange -pe -r

    提示Succeded即创建完成。

    此时将在当前用户下的个人项目中看到这个证书,图中MMC管理单元的使用可以参考这里。

    

   2、设置为信任

    由于创建的证书在个人域,且不在信任链中,wcf和iis目前不能使用这个证书,一次需要将其设置为信任。

    首先先将其导出到磁盘:证书上右键--所有任务--导出--选择导出私钥--设置私钥密码,完成后将得到一个pfx文件。

    然后进入上图的本地计算机,在个人域导入刚才那个pfx文件,完成后双击证书,在“证书路径”标签中提示“由于CA 根证书不在“受信任的根证书颁发机构”存储区中,所以它不受信任。”,此时证书仍然不能被使用,我的做法是在本地计算机的“受信任的根证书颁发机构”重复导入一次。此时两个证书都变成可信,即使将第二次导入的删除也没关系。

    以上做完没问题的话,双击证书后的状态应该是这样的:

    

  二、通过证书加密的项目

    1、创建wcf服务

      VS中新建“WCF服务应用程序”的项目,命名为WCF_HelloService,此时不用任何修改,已经是可运行的wcf服务,然后将其部署到iis,在浏览器中可使用http访问到服务信息:

      并重写Service1.scv.cs中的GetData()方法:

        public string GetData(int value){if (ServiceSecurityContext.Current != null){if (!ServiceSecurityContext.Current.IsAnonymous){return "Hello:" + ServiceSecurityContext.Current.PrimaryIdentity.Name + ";type=" + ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType;}return "Hello,你输入的是:" + value;}return "Hello ||未检测到证书:" + value;}

View Code

      下面是重点,编辑服务的Web.config文件,使其访问证书,这里尤其注意要注意用于各项配置互调的名称设置,如behaviorConfiguration和bindingConfiguration等:

<?xml version="1.0" encoding="utf-8"?>
<configuration><appSettings><add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/></appSettings><system.web><compilation debug="true" targetFramework="4.5.2"/><httpRuntime targetFramework="4.5.2"/><httpModules><add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/></httpModules></system.web><system.webServer><modules runAllManagedModulesForAllRequests="true"><remove name="ApplicationInsightsWebTracking"/><add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"preCondition="managedHandler"/></modules><!--若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。--><directoryBrowse enabled="true"/><validation validateIntegratedModeConfiguration="false"/></system.webServer><system.serviceModel><services><service name="WCF_HelloService.HelloService" behaviorConfiguration="CustomBehavior"><endpointbinding="mexHttpBinding"contract="IMetadataExchange"address="mex" /><endpoint address="" binding="wsHttpBinding" contract="WCF_HelloService.IHelloService" bindingConfiguration="CustomBinding"/></service></services><behaviors><serviceBehaviors><behavior name="CustomBehavior"><!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 --><serviceMetadata httpGetEnabled="true"/><!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 --><serviceDebug includeExceptionDetailInFaults="false"/><!--add by Lbh--><serviceCredentials><!-- 服务端采用证书详细配置    findValue :创建证书名称   storeName:证书储存详细位于哪    storeLocation :证书储存位于当前本机用户  X509FindType : x509查找证书主题名--><serviceCertificate findValue="HelloServiceClient" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/><!--客户端验证方式--><clientCertificate><authentication certificateValidationMode="None"/></clientCertificate></serviceCredentials></behavior></serviceBehaviors></behaviors><serviceHostingEnvironment multipleSiteBindingsEnabled="true" /><!--add by Lbh--><bindings><wsHttpBinding><binding name="CustomBinding"><!--验证方式--><security mode="Message"><message clientCredentialType="Certificate"/></security></binding></wsHttpBinding></bindings></system.serviceModel>
</configuration>

View Code

      添加add by 注释是添加的内容,注意serviceCertificate节点,这里定义了目的证书的信息,请务必使其指向我们刚才配置好的证书,其他诸如命名空间、接口、类名等也应与项目对应。

      配置完成后如无问题,刷新刚才的web页面,我们仍然能看到服务启动成功的页面。

      2、配置客户端

      随便添加个winform程序,首先引用上面的服务,然后修改其app.config,同样需要注意behaviorConfiguration设置:

      

<?xml version="1.0" encoding="utf-8" ?>
<configuration><startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /></startup><system.serviceModel><bindings><wsHttpBinding><binding name="WSHttpBinding_IHelloService"><security mode="Message"><transport clientCredentialType="Windows" /><message clientCredentialType="Certificate" /></security></binding></wsHttpBinding></bindings><!--add by Lau--><behaviors><endpointBehaviors><behavior name="CustomBehavior"><clientCredentials><clientCertificate findValue="HelloServiceClient" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/><serviceCertificate><authentication certificateValidationMode="None"/></serviceCertificate></clientCredentials></behavior></endpointBehaviors></behaviors><client><endpoint address="http://localhost:8096/HelloService.svc" behaviorConfiguration="CustomBehavior"binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHelloService"contract="HelloService.IHelloService" name="WSHttpBinding_IHelloService"><identity><certificate encodedValue="AwAAAAEAAAAUAAAAmIXXyLpHnm+H6oDaCP03aIn03SsgAAAAAQAAABUCAAAwggIRMIIBeqADAgECAhC1V8uCAl/avEkX078G+PlRMA0GCSqGSIb3DQEBBAUAMB0xGzAZBgNVBAMTEkhlbGxvU2VydmljZUNsaWVudDAeFw0xNzA1MDgwNzE1NDBaFw0zOTEyMzEyMzU5NTlaMB0xGzAZBgNVBAMTEkhlbGxvU2VydmljZUNsaWVudDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1+nEnhCxXtfAFxOGgFgzBjcPeO2WmxQI5SC14e6S4yEz+ymJtfKBcEnRSCX7onQDRE5H9dPl9CqoNjI/nkU5OKZ789f5Jh7ISfDK0jfHPa2EYwKK3FwOwGFmx5YY2/7Eb/nmyq6gbroronBIioFU6mcZjkFmTQTDa2WnZJMIsikCAwEAAaNSMFAwTgYDVR0BBEcwRYAQhYkF0TiSQwHAV/0wgMmvE6EfMB0xGzAZBgNVBAMTEkhlbGxvU2VydmljZUNsaWVudIIQtVfLggJf2rxJF9O/Bvj5UTANBgkqhkiG9w0BAQQFAAOBgQA0LvNliWDaWtU4YkqXI8JU9/2mIHO2PK4EVUmUYJu0oxFNEeRcX8ZpAAAA26gRYN+J4IjC1F33NjRG/tzkGJeaTBdOl2SkJo8LqD2D7YfOcMaXfrAsAOcEP5e4z2Z4aZlZp1tOjf0X5SZ6QL4FbPiiJog+1UbF/z5J097peDU7Bw==" /></identity></endpoint></client></system.serviceModel>
</configuration>

View Code

      与服务端类似地,clientCertificate节点定义了客户端证书,本例中使用了服务端相同的证书,也可以创建另一个专供客户端使用。certificate节点的内容来自服务端,引用WCF服务操作完成后会自动生成,如果没有,请检查WCF的web.config中是否定义为baseHttpBinding而不是wsHttpBinding(正确的是后者)。

      最后在winform加上基本的button和txtResult,并在button按钮事件写入代码:

      

        private void button1_Click(object sender, EventArgs e){try{HelloService.HelloServiceClient client = new HelloService.HelloServiceClient();string result = client.GetData(DateTime.Now.Second);txtResult.Text = result;}catch (Exception ex){this.txtResult.Text = ex.ToString();}}

View Code

      运行程序,得到正常结果如图:

      

      并且通过http拦截到的都是密文:

      

      至此,第一个证书项目完成,demo请到文章结尾处下载。

  三、通过证书+帐号密码加密的项目

    1、创建WCF服务

      按上面步骤创建好服务,首先添加IdentityModel库的引用:

      

      然后创建用于校验的CustomUserPassword类,代码如下:

using System.IdentityModel.Selectors;
using System.ServiceModel;namespace TestUserPassService
{public class CustomUserPassword : UserNamePasswordValidator{public override void Validate(string userName, string password){if (userName != "admin" || password != "admin"){//throw new SecurityNegotiationException("验证用户名和密码时,未通过检测");// 此异常可能无法被客户端捕获throw new FaultException("用户名或者密码错误!");}}}
}

View Code

      最后修改web.config文件,可以看到增加了userNameAuthentication节点,定义的正是自定义的校验类:

<?xml version="1.0" encoding="utf-8"?>
<configuration><appSettings><add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/></appSettings><system.web><compilation debug="true" targetFramework="4.5.2"/><httpRuntime targetFramework="4.5.2"/><httpModules><add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/></httpModules></system.web><system.webServer><modules runAllManagedModulesForAllRequests="true"><remove name="ApplicationInsightsWebTracking"/><add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"preCondition="managedHandler"/></modules><!--若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。--><directoryBrowse enabled="true"/><validation validateIntegratedModeConfiguration="false"/></system.webServer><system.serviceModel><services><service name="TestUserPassService.Service1" behaviorConfiguration="CustomBehavior"><endpointbinding="mexHttpBinding"contract="IMetadataExchange"address="mex" /><endpoint address="" binding="wsHttpBinding" contract="TestUserPassService.IService1" bindingConfiguration="CustomBinding"/></service></services><!--add by Lbh--><behaviors><serviceBehaviors><behavior name="CustomBehavior"><!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false --><serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/><!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 --><serviceDebug includeExceptionDetailInFaults="false"/><serviceCredentials><!-- 服务端采用证书详细配置    findValue :创建证书名称   storeName:证书储存详细位于哪    storeLocation :证书储存位于当前本机用户  X509FindType : x509查找证书主题名--><serviceCertificate findValue="HelloServiceClient" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/><!--客户端验证方式--><clientCertificate><authentication certificateValidationMode="None"/></clientCertificate><userNameAuthentication  customUserNamePasswordValidatorType="TestUserPassService.CustomUserPassword,TestUserPassService" userNamePasswordValidationMode="Custom"/></serviceCredentials></behavior></serviceBehaviors></behaviors><protocolMapping><add binding="basicHttpsBinding" scheme="https"/></protocolMapping>    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/><!--add by Lbh--><bindings><wsHttpBinding><binding name="CustomBinding"><security mode="Message"><transport clientCredentialType="Windows"/><message clientCredentialType="UserName"/></security></binding></wsHttpBinding></bindings></system.serviceModel></configuration>

View Code

      注意clientCredentialType节点,这里采用映射到Windows账户的方式,这是颇为常用和可靠的方式。

      部署到iis,没问题的话,我们仍然可以使用浏览器通过http访问到服务。

    2、创建测试客户端

      新建winform客户端,首先添加引用,修改后的app.config如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /></startup><system.serviceModel><bindings><wsHttpBinding><binding name="WSHttpBinding_IService1"><!--add by Lbh--><security mode="Message"><transport clientCredentialType="Windows" /><message clientCredentialType="UserName" /></security></binding></wsHttpBinding></bindings><client><endpoint address="http://localhost:8095/Service1.svc" binding="wsHttpBinding"bindingConfiguration="WSHttpBinding_IService1" contract="Service1.IService1"name="WSHttpBinding_IService1"><identity><certificate encodedValue="AwAAAAEAAAAUAAAAmIXXyLpHnm+H6oDaCP03aIn03SsgAAAAAQAAABUCAAAwggIRMIIBeqADAgECAhC1V8uCAl/avEkX078G+PlRMA0GCSqGSIb3DQEBBAUAMB0xGzAZBgNVBAMTEkhlbGxvU2VydmljZUNsaWVudDAeFw0xNzA1MDgwNzE1NDBaFw0zOTEyMzEyMzU5NTlaMB0xGzAZBgNVBAMTEkhlbGxvU2VydmljZUNsaWVudDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1+nEnhCxXtfAFxOGgFgzBjcPeO2WmxQI5SC14e6S4yEz+ymJtfKBcEnRSCX7onQDRE5H9dPl9CqoNjI/nkU5OKZ789f5Jh7ISfDK0jfHPa2EYwKK3FwOwGFmx5YY2/7Eb/nmyq6gbroronBIioFU6mcZjkFmTQTDa2WnZJMIsikCAwEAAaNSMFAwTgYDVR0BBEcwRYAQhYkF0TiSQwHAV/0wgMmvE6EfMB0xGzAZBgNVBAMTEkhlbGxvU2VydmljZUNsaWVudIIQtVfLggJf2rxJF9O/Bvj5UTANBgkqhkiG9w0BAQQFAAOBgQA0LvNliWDaWtU4YkqXI8JU9/2mIHO2PK4EVUmUYJu0oxFNEeRcX8ZpAAAA26gRYN+J4IjC1F33NjRG/tzkGJeaTBdOl2SkJo8LqD2D7YfOcMaXfrAsAOcEP5e4z2Z4aZlZp1tOjf0X5SZ6QL4FbPiiJog+1UbF/z5J097peDU7Bw==" /></identity></endpoint></client></system.serviceModel>
</configuration>

View Code

      可以看到,配置相比上一个项目简单许多,因为这里的客户端无需调用证书,只需定义加密类型。

      添加两个textbox一个button和一个textResult,定义按钮事件代码:

using System;
using System.Windows.Forms;namespace TestUserPassService_Client
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void textBox1_TextChanged(object sender, EventArgs e){}private void textBox2_TextChanged(object sender, EventArgs e){}private void button1_Click(object sender, EventArgs e){try{Service1.Service1Client client = new Service1.Service1Client();// 传入帐号密码client.ClientCredentials.UserName.UserName = this.textBox1.Text;client.ClientCredentials.UserName.Password = this.textBox2.Text;string result = client.GetData(DateTime.Now.Second);txtResult.Text = result;}catch (Exception ex){this.txtResult.Text = ex.ToString();}}}
}

View Code

      运行客户端,正确的结果如图:

      

      假若修改传入的帐号密码,结果如下:

      

      查看http传输内容,同样是密文:

      

      至此,本项目完成,demo可在文章结尾处下载。

  四、总结

    其实wcf加密操作没有太高深的内容(或者说暂且不用理会里面高深的内容),繁琐的部分在于web.config和app.config的配置,尤其bindingConfiguration这类名称命名上,由于网上教程众多,东拉一块西扯一块拼起来是用不了的。比如我这样的萌新调通两个项目就花了2天时间,因此这篇文章也尽可能将容易踩到的雷点暴露出来,供后来者们借鉴。当然篇幅和能力有限不能面面俱到,也请各位谅解,有问题可以在下面回复或者请教谷歌。

  五、demo下载

  

  证书demo

  

    证书+帐号密码demo

--------------------------------------------------------------------------------更新01------------------------------------------------------------------------------------------------------

  如果web访问配置好的服务提示“密钥集不存在”的问题,请按一下方法处理:

  进入路径:C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys(vista之后可用)

  找到刚才创建的证书文件,如果你不确定,可以参考这里

  然后右键-属性-安全,保证IIS_IUSRS用户有读取该文件的权限(本机测试时IIS是由这个用户运行的,其他电脑可能会有不同。)即可。

转载于:https://www.cnblogs.com/lbhqq/p/6830875.html

WCF加密操作(包括证书和证书+帐号密码)相关推荐

  1. 爱特文管php,爱特文管帐号密码md5加密版

    1. 空间商都偷源码了,还要登你爱特文管操作嘛 Redmi K20 Pro (情醉中国风/@Ta/2020-07-10 15:17) 2. @情醉中国风,偷源码,看admin.php里面的密码,然后撞 ...

  2. Wireshark分析实战:某达速递登录帐号密码提取

    "使用某达速递的官网登陆及APP登录,来学习Wireshark的使用." 在如今这个HTTPS深入人心的情况下,作为一个也不算很小的快递,某达速递,不但全站HTTP,而且登录帐号密 ...

  3. dede修改mysql用户名密码_老李教你快速学会织梦dedecm后台修改帐号密码教程

    原创 老李教你快速学会织梦dedecms后台管理员密码重置和修改教程. 织梦dedecms建站系统在目前还是算很流行的门户网站建站系统,功能强大易于操作,今天老李就发生了一件很丢脸的事,就是忘记了后台 ...

  4. 如何获取电信(光)猫路由器的超级帐号密码

    只有得到电信光猫路由器的超级帐号密码,才能修改设置自动拨号和无线功能. 在浏览器输入192.168.1.1,输入普通帐号和密码,这个在猫上面能找到: 登录后在浏览器输入192.168.1.1/back ...

  5. git不再询问帐号密码_您的密码不再是秘密,第1部分

    git不再询问帐号密码 当然,标题是一个把戏. 目前,您的密码仍然是秘密的. 为确保它保持不变,请尝试对自己回答以下问题: 您的密码强度如何 ? 为了防止其他人发现它们,它们应该有多强? 您的密码习惯 ...

  6. 找回在foxmail中登录过的帐号密码

    一.场景 一直用工作电脑的foxmail收发邮件,在家想登录邮箱时,居然忘记了密码,试不出来: 就想着工作电脑中的foxmail一直是自动登录,应该将帐号密码记录在某处,一试果然可行,现分享给大家 二 ...

  7. HexorBase 登陆、执行语句、数据库帐号密码破解

    HexorBase Tool:整合了目前几大主流的数据库,包括登陆,执行语句,数据库帐号密码破解等功能. 安装HexorBase Tool,安装文件:hexorbase_1.0_all.deb 下载地 ...

  8. 从Discuz迁移帐号密码到NodeBB

    从Discuz迁移帐号密码到NodeBB 最近论坛要从Discuz改版到NodeBB中,由于原有dz框架使用了较长时间,积累了一定的用户数,为了对用户进行无感知的迁移,首先需要将账户登录的问题解决. ...

  9. 重装系统后服务器不提示用户密码,明明没有设置密码,重装系统后开机要求输入帐号密码咋办?...

    原标题:明明没有设置密码,重装系统后开机要求输入帐号密码咋办? 时常有用户在重装系统后出现开机需要输入帐号密码的情况,其实这是由于Administrator管理员帐号被停用导致的,出现这情况只要进入安 ...

最新文章

  1. 深入理解java虚拟机---读后笔记(垃圾回收)
  2. 聊聊我对开发项目选技术的看法
  3. python mysql批量更新_Python批量删除mysql中千万级大量数据的脚本分享
  4. Chrome调试模拟iPhone6时body显示980*1742
  5. BS下实现WIN7下Aero效果
  6. body curl 设置post_curl 命令详解
  7. 数据结构之优先队列:优先队列的介绍与基础操作实现,Python代码实现——14
  8. linux常用命令和配置
  9. 3-1:常见任务和主要工具之软件包管理
  10. android7 编译配置摄像头,MTK平台新增摄像头指南 -- 已更新android 7.0路径的更改。...
  11. 去中心化云存储聚合器ColdStack S3 API开启私人Beta版测试
  12. 如何搞懂容器的核心技术点?
  13. java executor_Java并发编程73道面试题及答案——面试稳了
  14. JDK8 官方下载地址
  15. Python语言程序设计----【第8周 程序设计方法学】之8.2 Python程序设计思维
  16. PCBLayout相关注意事项和常见问题
  17. 【精品】MySQL 自定义函数
  18. web手机服务器系统,web手机服务器系统
  19. mysql 视图 多个 select_MySQL中Update、select联用操作单表、多表,及视图与临时表的区别...
  20. 地理Essay范文的组成剖析

热门文章

  1. 4行CSS实现【表格内容超过一行的部分,用省略号代替】【支持IE6】
  2. c#_winform_选择文件保存路径
  3. mysql数据依赖关系_发现数据库对象的依赖关系
  4. android手机上的ancs,Android BLE开发之操作IOS ANCS
  5. html中open打开新网页,JavaScript-打开新窗口(window.open)
  6. 反向工程_反向工程:宾利精心复刻了1929 Blower车型
  7. r语言 聚类求和_R语言聚类分析,如何导出将分类结果?
  8. c#split方法拆分为数据_Dexplot:基于pandas,比matplotlib更简单的数据可视化和数据分析工具...
  9. 为什么使用HashMap需要重写hashcode和equals方法_为什么要重写 hashcode 和 equals 方法?...
  10. GitLab 已迁移至谷歌云平台,并表示目前运行良好