我正在使用 WCF 开发客户端-服务器应用程序。WCF 服务使用数字证书进行保护。我正在使用消息安全性,因为我要求客户端在对服务器的任何调用中提供会员用户名/密码。该服务器由 Windows 服务托管。我已经在生产服务器上安装了证书服务并使用它来创建服务器身份验证数字证书。
服务器的数字证书使用 sha1 作为具有 1024 位公钥的散列算法。
客户端 WCF 代理由 Visual Studio 生成(通过添加服务引用)。在我的客户端中,我使用的是 WCF 代理的单例实例。
问题是当 WCF 的安全模式设置为"Message"或"TransportWithMessage"时,应用程序在我的生产服务器(专用云服务器和我的本地计算机充当客户端)上的性能很糟糕。
当服务器和客户端在同一台机器上时,应用程序在我的本地机器和生产服务器上运行得非常快。这排除了与 SQL 查询相关的任何性能问题。
比较具有和不具有安全性的性能。我使用了以下操作:
操作:
- 检查登录凭据:调用的测试函数,如果返回安全异常,则凭据不正确。
- Get List:一个返回 11 个(EF DbContext)实体列表的函数。
- 按 ID 获取记录:返回加载了一些“单一多重性”导航属性的单个实体。
我使用 WireShark 记录对这些操作的服务调用数据的持续时间和大小。我已经重复测试了 wsHttpBinding 的安全性、netTcpBinding 的安全性和 netTcpBinding 的安全性,结果如下:
当客户端和服务器在同一台机器上时,任何操作的持续时间总是小于一秒。
这是 WCF 服务器的配置文件:您会注意到我有两个绑定和两个行为,一个用于安全通信,另一个用于不安全通信。
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="HS" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=HS;Integrated Security=True" providerName="System.Data.SqlClient"/>
<add name="HSContext" connectionString="metadata=res://HS.Model/Model.csdl|res://HS.Model/Model.ssdl|res://HS.Model/Model.msl;provider=System.Data.SqlClient;provider connection string="data source=.\SQLEXPRESS;initial catalog=HS;integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.2"/>
<authentication mode="Forms">
<forms name=".HSYAUTH" loginUrl="~/Account/LogOn" cookieless="UseCookies" protection="All" slidingExpiration="true" timeout="2880"/>
</authentication>
<machineKey validationKey="..." decryptionKey="..." validation="HMACSHA256" decryption="AES"/>
<membership defaultProvider="SqlMembershipProvider" userIsOnlineTimeWindow="15" hashAlgorithmType="SHA256">
<providers>
<clear/>
<add applicationName="HS" name="SqlMembershipProvider" connectionStringName="HS" passwordFormat="Hashed" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="6" maxInvalidPasswordAttempts="5" enablePasswordReset="true" enablePasswordRetrieval="false" passwordAttemptWindow="10" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" type="System.Web.Security.SqlMembershipProvider"/>
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="SqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="HS" applicationName="HS"/>
</providers>
<properties>
<add name="WebSettingsTestText" type="string" readOnly="false" defaultValue="DefaultText" serializeAs="String" allowAnonymous="false"/>
</properties>
</profile>
<roleManager enabled="true" defaultProvider="SqlRoleProvider">
<providers>
<clear/>
<add connectionStringName="HS" applicationName="HS" name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider"/>
<add applicationName="HS" name="WindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider"/>
</providers>
</roleManager>
</system.web>
<system.serviceModel>
<services>
<service name="HS.Services.HS" behaviorConfiguration="SecureServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://0:808/Services/HS.svc"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" contract="HS.Services.IHS" bindingConfiguration="SecureBinding">
<identity>
<dns value="{my server ip address}"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SecureServiceBehavior">
<serviceMetadata/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<serviceCertificate findValue="CN={my server ip address}" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>
<clientCertificate>
<authentication revocationMode="NoCheck"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="SqlMembershipProvider"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider"/>
<serviceThrottling maxConcurrentCalls="128" maxConcurrentSessions="128" maxConcurrentInstances="128"/>
</behavior>
<behavior name="InsecureServiceBehavior">
<serviceMetadata/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="SqlMembershipProvider"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider"/>
<serviceThrottling maxConcurrentCalls="128" maxConcurrentSessions="128" maxConcurrentInstances="128"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="SecureBinding" receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="20000000" portSharingEnabled="false">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
<readerQuotas maxDepth="32" maxArrayLength="200000000" maxStringContentLength="200000000"/>
</binding>
<binding name="NoSecureBinding" receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="20000000" portSharingEnabled="true">
<security mode="None">
</security>
<readerQuotas maxDepth="32" maxArrayLength="200000000" maxStringContentLength="200000000"/>
</binding>
</netTcpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
这是 WCF 客户端的配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IHS" receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="20000000" portSharingEnabled="false">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
<binding name="NetTcpBinding_IHS_Insecure" receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="20000000">
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://{my server ip address}:808/Services/HS.svc" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IHS" contract="ServiceReference.IHS"
name="NetTcpBinding_IHS">
</endpoint>
</client>
</system.serviceModel>
</configuration>
一周以来,我一直在努力解决这个问题,但没有任何显着进展。具有安全性的 WCF 慢吗?还是我做错了什么?