【发布时间】:2014-11-28 12:48:58
【问题描述】:
我试图了解 WCF 中的身份验证是如何工作的。有一个带有 https 端点的自托管服务,它绑定到我的一个证书。
时一切正常
security mode="None"
那么即使在不同的机器上也能正常工作。与
的情况相同
mode="Transport" and <transport clientCredentialType="None"/>
。当我尝试通过 UserName 添加验证时,它工作正常,但仅在本地主机上,当托管在不同的机器上时,我收到一个错误:
“从其他人那里收到了一个不安全的或不正确的安全故障 派对……”
为什么它不适用于用户名密码验证?
EDIT2:我发现服务器上抛出了以下异常并被捕获(但仅在不同的机器上):“安全时间戳无效,因为它的创建时间('2014-11-29T01:30:48.824Z')是在未来。当前时间是“2014-11-28T14:51:52.704Z”,允许的时钟偏差是“00:05:00”。”。我不知道这个创建时间在哪里,但肯定不是来自另一台机器。会发生什么?
第二个问题是关于证书的。托管 https 并将地址绑定到证书时,是否应将此证书作为受信任的方式安装在客户端计算机上? (我用 netsh 绑定它) 如果没有以下代码,我将无法连接到我的 wcf 服务:
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
是在客户端进行证书验证吗?它检查它是否存在以及它是否由受信任的发行者发行?
编辑: 附加问题: 当我尝试使用浏览器输入服务安全端点时,它说此连接不安全,不可信来源等。在我的服务机器上,我已将证书绑定到 https,并且该证书是由“CertificateIssuer”颁发的 MyCertificate。现在我将颁发者证书安装到服务和客户端机器中 - 我的意思是“CertificateIssuer”进入受信任的根证书颁发机构”,当我从同一台机器进入时我仍然不是受信任的事件。我应该如何将它配置为受信任?
服务器配置:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="true"/>
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="SdrConfigExample.e2e"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<services>
<service name="WcfService1.TestService" behaviorConfiguration="ServiceUsernameValidation">
<host>
<baseAddresses>
<add baseAddress="https://localhost:8734/Services/"/>
<add baseAddress="http://localhost:8735/Wsdl/"/>
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="Test" binding="basicHttpBinding" contract="WcfService1.ITestService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
<behavior name="ServiceUsernameValidation">
<serviceMetadata httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfSecurity.PasswordValidator,WcfSecurity"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
客户端配置:
<?xml version="1.0"?>
<configuration>
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="SdrConfigExample.e2e"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ITestService">
<security mode="TransportWithMessageCredential" >
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://175.28.233.153:8734/Services/Test" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ITestService" contract="ServiceReference1.ITestService"
name="BasicHttpBinding_ITestService" />
</client>
</system.serviceModel>
</configuration>
服务器代码:
ServiceHost host = new ServiceHost(typeof(TestService));
var uri = host.Description.Endpoints[0].Address.Uri;
var cert = FindCertificate("CN=MyCertificate");
if (!ReserveAddressForHttps(uri.Host, uri.Port, cert, 5000))
{
throw new Exception("Failed to assign service certificate into local interface.");
}
host.Open();
host.Description.Endpoints.ToList().ForEach(x => Console.WriteLine(x.Address));
Console.WriteLine();
Console.WriteLine("Service started...");
Console.ReadLine();
host.Close();
客户端代码:
TestServiceClient client = new TestServiceClient();
client.ClientCredentials.UserName.UserName = "hej";//this is valid
client.ClientCredentials.UserName.Password = "hej";
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
try
{
var result = client.GetData(123);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
【问题讨论】: