在开发过程中,经常需要确保服务的安全性,这通常涉及到使用SSL和ASP.NET身份验证提供程序。本文将介绍在配置WCF服务时遇到的一些常见问题及其解决方法。
在配置WCF服务时,可能会遇到各种错误,尤其是当涉及到安全令牌时。例如,当尝试将wsHttpBinding
的security
消息的clientCredentialType
更改为Username
时,可能会遇到错误:“安全令牌请求包含无效或格式错误的元素”。
在遇到此类错误时,首先需要启用日志记录,以便更详细地了解发生了什么。这可以通过使用svcTraceviewer.exe
工具来实现。这个工具包含在Windows Vista SDK中,尽管可能只需要.NET 3.0 SDK。
在客户端和服务端启用日志记录后,可以通过查看日志来获取更详细的错误信息。例如,可能会看到错误:“x509证书不受信任”或“身份不匹配,请尝试将'www.domain.com'更改为'domain.com'”。这些错误信息比之前的模糊错误更有帮助。
为了解决SSL问题,可以使用makecert.exe
工具创建一个测试证书。例如:
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0>makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=localhost -sky exchange -pe
为了让WSE能够从本地计算机证书存储中获取X.509私钥,需要授予ASP.NET服务运行账户相应的权限。默认情况下,只有所有者和系统账户可以访问证书的私钥。
要授予ASPNET账户访问私钥的权限,请按照以下步骤操作:
C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
文件夹。接下来,需要运行MMC并添加证书插件。可以使用这个插件查看本地计算机中安装的个人证书,并在文件夹之间复制它们。需要找到与serviceBehaviors serverCredentials serviceCertificate
中的findvalue
属性匹配的友好名称的证书。
最后,需要配置web.config
和app.config
文件,以确保服务和客户端正确地使用SSL和ASP.NET身份验证提供程序。
以下是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>
<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="http://localhost:4358/FamilyOrganizer.AuroraSync.WCFService/AuroraSyncService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IAuroraSyncService" contract="FamilyOrganizer.Aurora.Sync.WCFService.IAuroraSyncService" name="WSHttpBinding_IAuroraSyncService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="myClientBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>