我尝试以下方法:
现在我已将上面的场景实现为三个LinqPad脚本:client.linq
,sts.linq
(自托管WCF服务)和service.linq
(自托管WCF服务)。它们都可以在https://github.com/codeape2/WCF_STS
我需要一些帮助才能让它发挥作用。
使用client.linq
中的以下代码,我可以调用我的STS并获得SAML断言:
SecurityToken GetToken()
{
var binding = new BasicHttpBinding();
var factory = new WSTrustChannelFactory(binding, stsAddress);
factory.TrustVersion = TrustVersion.WSTrustFeb2005;
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Symmetric,
AppliesTo = new EndpointReference(serviceAddress)
};
return factory.CreateChannel().Issue(rst);
}
下一步,我使用以下代码(尝试)使用SAML断言调用我的服务:
var binding = new WSFederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.Security.Message.EstablishSecurityContext = false;
var factory = new ChannelFactory<ICrossGatewayQueryITI38>(
binding,
new EndpointAddress(new Uri(serviceAddress), new DnsEndpointIdentity("LocalSTS"))
);
factory.Credentials.SupportInteractive = false;
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.None;
var proxy = factory.CreateChannelWithIssuedToken(token);
var response = proxy.CrossGatewayQuery(
Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:ihe:iti:2007:CrossGatewayQuery", "Hello world")
);
接下来会发生什么我完全不理解。当我运行脚本时,我有小提琴运行,这就是我所看到的:
/STS
的第一次请求(按预期方式) proxy.CrossGatewayQuery
会导致三次调用/Service
:
2.1。具有操作http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
2.2。具有操作http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue
2.3。带有操作urn:ihe:iti:2007:CrossGatewayQuery
的最终SOAP调用。使用Fiddler,我注意到SOAP安全头包含第一步中的SAML断言。
最终调用导致服务返回SOAP错误:无法验证消息中至少有一个安全令牌。保存的Fiddler请求/响应日志位于:https://drive.google.com/file/d/0B-UZlLvBjjB2S050TXRhVEo2Vmc/view?usp=sharing
如果有人能够了解以下情况,我将非常感激:
RST/Issue
发送RSTS/Issue
和/Service
个请求(上面的步骤2.1和2.2)?答案 0 :(得分:1)
第一个问题是重新协商服务凭证。
这一改变解决了这个问题:
binding.Security.Message.NegotiateServiceCredential = false
然后服务必须启用WIF配置:
host.Credentials.UseIdentityConfiguration = true;
host.Credentials.IdentityConfiguration = CreateIdentityConfig();
IdentityConfiguration CreateIdentityConfig()
{
IdentityConfiguration identityConfig = new IdentityConfiguration(false);
//AUDIENCE URI
//the token we receive contains this value, so if do not match we fail
identityConfig.AudienceRestriction.AllowedAudienceUris.Add(new Uri($"http://{Environment.MachineName}:8000/Service"));
//ISSUER NAME REGISTRY explicit the thumbprint of the accepted certificates, if the token coming in is not signed with any of these certificates then is considered invalid
var issuerNameRegistry = new ConfigurationBasedIssuerNameRegistry();
issuerNameRegistry.AddTrustedIssuer("81 5b 06 b2 7f 5b 26 30 47 3b 8a b9 56 bb 9f 9f 8c 36 20 76", "signing certificate sts"); //STS signing certificate thumbprint
identityConfig.IssuerNameRegistry = issuerNameRegistry;
identityConfig.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
return identityConfig;
}
还有其他更改,github repo更新了在master
分支中工作的代码。
感谢MS的支持,他让我了解了这一点。