WCF学习笔记(三)—— WCF安全模式:基于用户名、密码、X.509的身份验证
2009-06-30 18:02 羊鸵 阅读(1378) 评论(5) 编辑 收藏 举报学习这个花了我N天的工夫,一直搞不定那个X.509的证书,不过还不算太笨,终于弄了出来。
X.509 比较适合验证 "客户机" 的身份,而另外一方面,我们可能需要针对具体的 "用户" 进行验证。
1.首先我们需要一个数字证书。
开始>>程序>>Microsoft Visual Studio 2008>>Visual Studio Tools>>Visual Studio 2008 Command Prompt
makecert -r -pe -n "CN=CACert" -sr LocalMachine -ss My -sky exchange
其实 LocalMachine 代表我们这个证书保存在"计算机帐户"中;My表示保存在"个人"这个类别下.
开始>>运行>>mmc 启动控制台
在 文件>>添加/删除管理单元>>添加 中添加证书的管理,帐户为"计算机帐户",管理单元管理的计算机为"本地计算机"
然后如下图可见,我们在"个人>>证书"目录可以找到我们刚才生成的证书"CACert".双击这个证书我们可以查看他的信息.
因为我们是自己生成的证书,所以 该CA根证书不受信任.
这个不受信任给接下来的工作制造了很多麻烦,我不知道高手是怎么解决的.
我解决的办法是先选择这个证书,右键选择"复制",然后展"开受信任的根证书颁发机构>>证书",右键点击证书,选择"粘贴".然后再查看这个人目录下的证书,这个证书就变成可以信任的了.
将来要部署的话可以导出这个证书,去其他机器上安装.
当然,这样做还是不够的.在以后的验证中,会发现IIS没有权限去读取这个证书的密钥.老是提示"密钥集不存在。".为了克服这个问题,我们需要分配一些权限.
在XP中我们给ASPNET这个帐户分配权限就可以了,再2003中,我们需要给NT AUTHORITY\NETWORK SERVICE这个帐户分配一些权限.
我们找个工具帮组我们一下:FindPrivateKey.exe
安全期间,还是自己去下一个比较好.
他可以帮我们找到我们密钥的位置。
这是我输入了2次命令,区别就在最后的“-a”上,只是改变了下显示方式。后面要用到。
FindPrivateKey.exe My LocalMachine -t "a5 16 2b be 74 b1 ea 39 fb 3f 2c bc b7 db f3 42 8a a3 17 60"
My LocalMachine 表示证书的安装位置,"a5 16 2b be 74 b1 ea 39 fb 3f 2c bc b7 db f3 42 8a a3 17 60"是证书的“微缩图”,查看证书的”详细信息“里面可以看到。
然后我们按照查询的结果,找到这个文件,然后设置权限。当然我们用 cacls.exe 这个Windows这个自带的工具也可以。大家可以看下一个批处理文件。
echo ************
echo setting privileges on server certificates
echo ************
for /F "delims=" %%i in ('FindPrivateKey.exe My LocalMachine -t "a5 16 2b be 74 b1 ea 39 fb 3f 2c bc b7 db f3 42 8a a3 17 60" -a') do set PRIVATE_KEY_FILE=%%i
set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE
(ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET
echo %WP_ACCOUNT%
echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R
pause
证书的准备到这里基本就没什么问题了。 不过实际运用的时候,还是找个比较可靠的证书,这个工具生成的我不太放心。
2.用户名,密码验证
我们需要引用System.IdentityModel这个空间的内。他在位置在
C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.dl
然后我们可以在服务中添加一个验证用的类 :MyUserNamePasswordValidator
然后我们可以在web.config 中做一些配置
<bindings>
<wsHttpBinding>
<binding name="BooksServiceBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="WCFCAcertTest.Service.Service">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="BooksServiceBinding" contract="WCFCAcertTest.Contract.IService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceCredentials>
<serviceCertificate findValue="0593589181bedb74f42cd84433a82c4984ecd7d1"
storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
<clientCertificate>
<authentication certificateValidationMode="None"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFCAcertTest.Service.MyUserNamePasswordValidator,WCFCAcertTest.Service"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
加下划线的地方要注意下,其中 indValue="0593589181bedb74f42cd84433a82c4984ecd7d1"换成你证书的“微缩图”,中间需要去掉空格。
基本上没有什么问题了。
传一个我做的测试程序。WCFCAcertTest.rar