我是WCF,.NET,Web服务和所有内容的新手 - 事实上,我主要是一个java& SQL编码器,直到我接受当前的工作。
手头的任务:我们数据库中客户数据的一部分需要定期导出到第三方提供的数据库,并可通过Web服务访问,而Web服务又通过提供的STS进行联合保护由第四方。
在WCF上花费了数小时混淆MSDN文档和大量博客文章后,我仍然无法让STS与我交谈,我得到的只是(400) Bad Request.
。
我的代码:
private static SecurityToken RequestSecurityToken()
{
WSHttpBinding binding = new WSHttpBinding();
binding.AllowCookies = true;
WSHttpSecurity security = new WSHttpSecurity();
security.Mode = SecurityMode.TransportWithMessageCredential;
security.Message.ClientCredentialType = MessageCredentialType.Certificate;
security.Message.NegotiateServiceCredential = true;
security.Message.EstablishSecurityContext = false;
binding.Security = security;
WSTrustChannelFactory factory = new WSTrustChannelFactory(binding, "https://FOURTH_PARTY_STS");
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "CUSTOMER_CERTIFICATE");
RequestSecurityToken rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
AppliesTo = new EndpointReference("https://THIRD_PARTY_WS"),
TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"
};
rst.Claims.Dialect = "http://docs.oasis-open.org/wsfed/authorization/200706/authclaims"; // Taken from an exception message
rst.Claims.Add(new RequestClaim("urn:tgic:names:ISTS:1.0:user:PartnerId", false, "CUSTOMER_ID"));
return factory.CreateChannel().Issue(rst);
}
生成这个SOAP主体:
<trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>https://THIRD_PARTY_WS</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<trust:Claims Dialect="http://docs.oasis-open.org/wsfed/authorization/200706/authclaims" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706">
<auth:ClaimType Uri="urn:tgic:names:ISTS:1.0:user:PartnerId" Optional="true">
<auth:Value>CUSTOMER_ID</auth:Value>
</auth:ClaimType>
</trust:Claims>
<trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
<trust:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</trust:TokenType>
</trust:RequestSecurityToken>
根据第四方的文件,STS期望这样的事情:
<wst:RequestSecurityToken
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsp15="http://www.w3.org/ns/ws-policy"
xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
Context="1aae57c8-092c-47a4-a5eb-c2ecbc21441d">
<wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</wst:TokenType>
<wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</wst:RequestType>
<wsp:AppliesTo>
<wsp15:URI>https://THIRD_PARTY_WS</wsp15:URI>
</wsp:AppliesTo>
<wst:Claims Dialect="urn:oasis:names:tc:SAML:2.0:assertion:AttributeStatementType">
<saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:Attribute Name="urn:tgic:names:ISTS:1.0:user:PartnerId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>9330931615</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</wst:Claims>
<wst:Lifetime>
<wsu:Created>2013-09-17T18:18:10Z</wsu:Created>
<wsu:Expires>2013-09-17T18:23:10Z</wsu:Expires>
</wst:Lifetime>
</wst:RequestSecurityToken>
该文档中的其他地方声明Context和Lifetime是可选的。因此,据我所知,我有两个问题:
我是否必须实现一些自定义序列化?如果是这样,我如何以及在何处将其挂钩到factory / binding / request?
答案 0 :(得分:0)
rst.AdditionalContext = new AdditionalContext(); rst.AdditionalContext.Items.Add(new ContextItem(new Uri(&#34; you_any_uri&#34;),PartnerId));
这种方式不需要任何序列化程序。
传递客户端凭据的另一种方法:使用RequestSecurityToken.Properties。在这种情况下,您必须实现自定义请求序列化程序。
var channelFactory = new WSTrustChannelFactory(binging, endpoint)
{
TrustVersion = TrustVersion.WSTrust13
};
channelFactory.WSTrustRequestSerializer = CustomRequestSerializer;
此处实施自定义WSTrust13RequestSerializer
public class CustomRequestSerializer: WSTrust13RequestSerializer
{
public override void WriteXmlElement(XmlWriter writer, string elementName, object elementValue, RequestSecurityToken rst,
WSTrustSerializationContext context)
{
var parameters = new string[1] {"paramname"};
if (parameters.Any(p => p == elementName))
{
writer.WriteElementString(elementName, (string)elementValue);
}
else
{
base.WriteXmlElement(writer, elementName, elementValue, rst, context);
}
}
public override void ReadXmlElement(XmlReader reader, RequestSecurityToken rst, WSTrustSerializationContext context)
{
var parameters = new string[1] {"paramname"};
var key = parameters.FirstOrDefault(reader.IsStartElement);
if (!string.IsNullOrWhiteSpace(key))
{
rst.Properties.Add(key, reader.ReadElementContentAsString());
return;
}
base.ReadXmlElement(reader, rst, context);
}
}