WCF:尝试使用自签名证书和'设置双向相互SSL身份验证;皮锈';
我正在尝试在同一台机器上使用相互SSL身份验证设置WCF服务和客户端 我有:WCF:尝试使用自签名证书和'设置双向相互SSL身份验证;皮锈';,wcf,ssl,certificate,Wcf,Ssl,Certificate,我正在尝试在同一台机器上使用相互SSL身份验证设置WCF服务和客户端 我有: 为服务器和客户端创建证书,并将其放入LocalMachine证书存储区。服务器和客户端私钥位于“个人”存储中,而公钥位于“受信任的人”存储中 我已经配置了一个WCF服务和客户机,每个服务和客户机都从存储中指定自己的证书引用,并且还设置要使用验证的其他方证书引用 注意:服务器证书颁发给计算机名,客户端调用的服务url为“https:\tokenservice\tokenservice.svc” 使用此配置,我希望客
- 为服务器和客户端创建证书,并将其放入LocalMachine证书存储区。服务器和客户端私钥位于“个人”存储中,而公钥位于“受信任的人”存储中
- 我已经配置了一个WCF服务和客户机,每个服务和客户机都从存储中指定自己的证书引用,并且还设置要使用验证的其他方证书引用
注意:服务器证书颁发给计算机名,客户端调用的服务url为“https:\tokenservice\tokenservice.svc”
使用此配置,我希望客户端安全地连接到服务,并且两端解析来自“受信任人员”存储的证书,但我收到以下错误,表明证书验证失败:
[身份验证异常:根据验证过程,远程证书无效。]
所以这并不像我预期的那样有效。有人能指出错误吗?还是我的期望不正确
WCF配置如下:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="CertificateForClient">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CertificateBehaviour">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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="true"/>
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"
trustedStoreLocation="LocalMachine" />
</clientCertificate>
<serviceCertificate findValue="CN='ServerCertificate which is machine name'"
storeLocation="LocalMachine" storeName="My"
x509FindType="FindBySubjectDistinguishedName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="TokenService.TokenService" behaviorConfiguration="CertificateBehaviour">
<endpoint contract="TokenService.ITokenService"
binding="wsHttpBinding" />
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding" address="mex">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://tokenservice" />
</baseAddresses>
</host>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
客户端配置:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ClientBehaviour">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=TokenClient"/>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" trustedStoreLocation="LocalMachine"></authentication>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="ClientBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://tokenservice/TokenService.svc"
behaviorConfiguration="ClientBehaviour"
binding="wsHttpBinding" bindingConfiguration="ClientBinding"
contract="TokenService.ITokenService" name="ToolClient">
<identity>
<dns value="MachineName" />
</identity>
</endpoint>
</client>
服务的基本URL应该是服务器证书名称 例如: 如果我的服务器证书名称是test.cer,那么我的服务URL应该 是
这就是您设置服务的方式吗?当在传输层使用相互SSL进行身份验证时,PeerTrust和ChainTrust提供的内置授权不起作用 老实说,PeerTrust在许多情况下都无法控制所需的授权过程 解决此问题的一种非常常见的方法是插入自定义ServiceAuthorizationManager并重写其OnAccess方法
<behavior name="ServerCertificateBehavior">
<serviceCredentials>
<serviceCertificate .... />
</serviceCredentials>
<serviceAuthorization serviceAuthorizationManagerType="MyCustomCertificateAuthorizationManager, MyWCFExtensions.Security" />
</behavior>
ServiceAuthorizationManager可以在几行代码中完成,以进行非常静态的简单证书检查,或者根据需要进行更复杂的检查
这个简单的概念证明有望帮助您开始:
public class MyCustomCertificateAuthorizationManager : ServiceAuthorizationManager
{
public override bool CheckAccess(OperationContext operationContext, ref Message message)
{
base.CheckAccess(operationContext, ref message);
string action = operationContext.IncomingMessageHeaders.Action;
List<string> approvedActions = new List<string>
{
"http://kramerica.lan/namespace/MySpecialMethod",
"http://kramerica.lan/namespace/AnotherMethod"
};
List<string> approvedThumbprints = new List<string>
{
"1aaffe105b31b79b66c31de3389203d42351683a",
"f1bcfbc6383bcbfa736473bcaf109987bbc2121a"
};
//One way is do the authorization based on the action if the endpoint is used for more than one operation with different ACL needs
if (approvedActions.Contains(action))
{
foreach (ClaimSet claimSet in OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets)
{
X509CertificateClaimSet certificateClaimSet = claimSet as X509CertificateClaimSet;
if (certificateClaimSet != null)
{
//Get the actual certificate used by the client
X509Certificate2 certificate = certificateClaimSet.X509Certificate;
//Here a real validation of certificate issuer chain etc. could be made
if (certificate != null)
{
//This proof-of-concept does authorization based on a static list of thumbprints but about anything os possible here.
//One could easily check if this certificate
//is present in the TrustedPeople store or some database backend
if (approvedThumbprints.Contains(certificate.Thumbprint))
return true;
}
}
}
}
return false;
}
}
公共类MyCustomCertificateAuthorizationManager:ServiceAuthorizationManager
{
公共覆盖布尔检查访问(OperationContext OperationContext,ref消息)
{
base.CheckAccess(operationContext,ref消息);
string action=operationContext.IncomingMessageHeaders.action;
列出已批准的操作=新列表
{
"http://kramerica.lan/namespace/MySpecialMethod",
"http://kramerica.lan/namespace/AnotherMethod"
};
列出已批准的指纹=新列表
{
"1aaffe105b31b79b66c31de3389203d42351683a“,
"F1BCFBC6383BCBFA736473BCAF109987BC2121A“
};
//一种方法是,如果端点用于具有不同ACL需求的多个操作,则根据操作进行授权
if(approvedActions.Contains(action))
{
foreach(OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSet中的ClaimSet-ClaimSet)
{
X509CertificateClaimSet certificateClaimSet=索赔集为X509CertificateClaimSet;
如果(certificateClaimSet!=null)
{
//获取客户端使用的实际证书
X509Certificate2 certificate=certificateClaimSet.X509Certificate;
//这里可以对证书颁发者链等进行真正的验证
如果(证书!=null)
{
//这一概念证明基于静态指纹列表进行授权,但这与操作系统可能的任何操作系统有关。
//可以很容易地检查此证书是否有效
//存在于TrustedPeople存储或某些数据库后端中
if(approvedThumbprints.Contains(certificate.Thumbprint))
返回true;
}
}
}
}
返回false;
}
}
这方面运气好吗?我很想看看你是怎么做到的。