C# 如何获取特定的RequestSecurityToken序列化

C# 如何获取特定的RequestSecurityToken序列化,c#,web-services,wcf,ws-federation,ws-trust,C#,Web Services,Wcf,Ws Federation,Ws Trust,我对WCF、.NET、web服务和所有东西都是新手——事实上,在我接受目前的工作之前,我主要是一名java和SQL程序员 手头的任务是:我们数据库中客户数据的一部分需要定期导出到由第三方提供并通过web服务访问的数据库中,而web服务又由第四方提供的STS进行联合保护 在花了好几个小时处理令人困惑的MSDN文档和大量关于WCF的博客文章之后,我仍然无法让STS与我交谈,我得到的只是一个(400)错误的请求。 我的代码: private static SecurityToken RequestSe

我对WCF、.NET、web服务和所有东西都是新手——事实上,在我接受目前的工作之前,我主要是一名java和SQL程序员

手头的任务是:我们数据库中客户数据的一部分需要定期导出到由第三方提供并通过web服务访问的数据库中,而web服务又由第四方提供的STS进行联合保护

在花了好几个小时处理令人困惑的MSDN文档和大量关于WCF的博客文章之后,我仍然无法让STS与我交谈,我得到的只是一个
(400)错误的请求。

我的代码:

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>

https://THIRD_PARTY_WS
客户识别码
http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue
http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
根据第四方的文件,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>

http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue
https://THIRD_PARTY_WS
9330931615
2013-09-17T18:18:10Z
2013-09-17T18:23:10Z
在该文档的其他地方,它声明了上下文和生存期是可选的。因此,在我看来,我有两个问题:

  • 如何将AppliesTo地址序列化为URI元素
  • 如何将声明序列化为Attribute/AttributeValue元素(使用正确的方言)
  • 我必须实现一些自定义序列化吗?如果是,我如何以及在何处将其挂接到工厂/绑定/请求

  • 要使用STS,必须使用WS2007HttpBinding而不是WSHttpBinding。您可以在WIFSDK中找到STS示例。它包含一个带有自定义标记的示例。看
  • 尝试在没有其他客户端参数的情况下发出securitytoken。制定一个只需发出令牌并调用RP方法的工作解决方案
  • 据我所知,您希望传递到STS自定义客户端凭据PartnerId。在我的项目中,我使用通过请求的附加上下文传递自定义凭据 rst.AdditionalContext=新的AdditionalContext(); AdditionalContext.Items.Add(newcontextItem(newURI(“you_any_Uri”),PartnerId))

    这种方式不需要任何序列化程序

    传递客户端凭据的另一种方法:使用。在这种情况下,必须实现自定义请求序列化程序

    var channelFactory = new WSTrustChannelFactory(binging, endpoint)
    {
           TrustVersion = TrustVersion.WSTrust13
    };
    channelFactory.WSTrustRequestSerializer = CustomRequestSerializer;
    
    这里是定制的实现

    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);            
        }
    }