MCF 服务(带成员资格提供程序) 通过 SSL





0/5 (0投票)
如何设置 MCF 服务以使用 ASP 会员提供者。
引言
我为我正在处理的一个客户端应用程序创建了一个简单的 MCF 服务。我想让通信使用 SSL,并使用 ASP 会员提供者作为身份验证源。这一切似乎都很简单,当我将 wsHttpBinding
安全消息的 clientCredentialType
更改为 Username
时,一切都很顺利。然后,开始了七个小时的相同非常无用的错误:“请求安全令牌的元素无效或格式错误。”
背景
在花费了七个小时搜索“请求安全令牌的元素无效或格式错误”之后,我偶然发现了一篇关于 svcTraceviewer.exe 的文章。无论如何,我找不到这个神奇的应用程序。最后,我找到并下载了 Windows Vista SDK,其中包含 .NET 3.0 SDK。我不知道为什么不只是一个 .NET 3.0 SDK,但我肯定没有打算在我的 XP 开发机器上安装 Vista SDK。无论如何,我添加了一些行来启用客户端和 MCF 服务上的日志记录。然后,我觉得我取得了一些进展。此时的错误与之前相同:“请求安全令牌的元素无效或格式错误。” 好的,那么现在怎么办?我现在知道当 clientCredentialType
="windows
" 时,一切都正常工作,但当我将其更改为 clientCredentialType
="UserName
" 时,错误就会再次出现。我知道 Microsoft 不会在 MSDN 帖子中以明文形式发送用户名和密码,这与客户端验证 SSL 证书有关,但即使我尝试在客户端使用我自己的 customCertificateValidator
,代码也从未被调用。我的问题是,在我阅读的所有文章中,我从未见过客户端 enpointBehaviors
serverCertificate
身份验证 certificateValidationMode
属性被设置。一旦我将其设置为 PeerOrChainTrust
,我就开始收到有意义的错误。例如:x509 证书不受信任 和 身份不匹配,请尝试将“www.domain.com”更改为“domain.com”。现在有了有意义的错误,我就可以找出需要修复的地方了。
使用代码
您需要做的第一件事是使用 makecert 可执行文件创建一个测试证书。我使用了
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0>makecert.exe
-sr LocalMachine -ss My -a sha1 -n CN=localhost -sky exchange -pe
我在 http://www.eggheadcafe.com/articles/20021231.asp 上找到了“如何授予 ASPNET 帐户访问证书的权限”。
为了让 WSE 从本地计算机证书存储中获取 X.509 私钥,它必须拥有访问权限。默认情况下,只有所有者和系统帐户可以访问证书的私钥。此外,默认情况下,ASP.NET 服务在 ASPNET 帐户下运行,并且该帐户无权访问私钥。
要授予 ASPNET 帐户访问私钥的权限,请授予 ASP.NET 运行所在的帐户对包含 WSE 需要在以下文件夹中检索的密钥的文件拥有完全控制权限。
C:\Documents and Settings\All Users\Application Data\
Microsoft\Crypto\RSA\MachineKeys
ASP.NET 工作进程运行所在的帐户由 Machine.config 文件中的 <processModel>
元素控制。设置 <processModel>
元素的 userName
属性来指定 ASP.NET 运行所在的帐户。默认情况下,userName
属性设置为特殊的计算机帐户,该帐户映射到安装 .NET Framework SDK 时创建的低权限 ASPNET 用户帐户。
- 打开 Windows 资源管理器。
- 导航到 C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys 文件夹。
- 选择包含 WSE 需要检索的密钥的文件。
- 在“文件”菜单中,选择“属性”。
- 在“安全”选项卡上,添加 ASPNET 帐户并选择“完全控制”选项。
注意:确定 MachineKeys 文件夹中的哪个密钥文件与证书相关联可能很困难。一个简单的解决方法是注意创建新证书时的时间和日期。在查看 MachineKeys 目录中的文件时,检查相应日期和时间的“修改日期”字段。
现在,运行 MMC 并添加两次证书插件。我将第一个添加为我的用户帐户,并将第二个添加为计算机。使用此 MMC 插件,您可以查看已作为个人证书安装在本地计算机上的证书,以及在文件夹之间进行复制和粘贴。您要查找的是本地计算机个人证书,如果存在一个友好名称与 serviceBehaviors serviceCredentials serviceCertificate
中的 findvalue
属性匹配的证书。应该注意的是,我还可以使用我之前在 IIS 中用于真实域的 godaddy 签名证书,即使 DNS 名称与 certname 不匹配,方法是编辑客户端身份。
这是我的 web.config
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="false"
maxMessagesToLog="30000"
maxSizeOfMessageToLog="200000"/>
</diagnostics>
<bindings>
<wsHttpBinding>
<binding name="AuroraSyncService">
<security mode="Message">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="AuroraSyncServiceBehavior"
name="AuroraSyncService">
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="AuroraSyncService"
contract="IAuroraSyncService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="AuroraSyncServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" />
<serviceCredentials>
<serviceCertificate findValue="localhost"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
<userNameAuthentication
userNamePasswordValidationMode="MembershipProvider"
membershipProviderName="MembershipSqlProvider" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\logs\servermessages.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
这是我的 app.config
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\logs\clientmessages.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="false"
maxMessagesToLog="30000"
maxSizeOfMessageToLog="200000"/>
</diagnostics>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IAuroraSyncService"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
bypassProxyOnLocal="false"
transactionFlow="false"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288"
maxReceivedMessageSize="1000000000"
messageEncoding="Text"
textEncoding="utf-8"
useDefaultWebProxy="true"
allowCookies="True">
<readerQuotas maxDepth="32"
maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession ordered="true"
inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="None"
proxyCredentialType="None"/>
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint
address="https://:4358/FamilyOrganizer.Aurora.
Sync.WCFService/AuroraSyncService.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IAuroraSyncService"
contract="FamilyOrganizer.Aurora.Sync.WCFService.IAuroraSyncService"
name="WSHttpBinding_IAuroraSyncService"
behaviorConfiguration="myClientBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="myClientBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
您的应用程序将需要创建 MCFclient
的实例并像这样设置用户名和密码
_WebServerSyncService = New WCFService.SyncServiceClient
_WebServerSyncService.ClientCredentials.UserName.UserName = myUserName
_WebServerSyncService.ClientCredentials.UserName.Password = myPassword
关注点
关于安全通道的那些含糊不清的错误惹恼了我。为什么不给出类似这样的错误:抱歉,客户端未设置为信任此证书,请尝试更改此属性,就像 MCF 抛出的所有其他错误一样。
历史
- 添加了 ASPNET 权限部分
- 修复了一些拼写错误
- 格式化 XML 以防止滚动