2015-05-04 2 views
0

Я новичок в WCF, .NET, веб-сервисах и обо всем - на самом деле, я был главным образом java & SQL-кодер, пока не взял на себя текущую работу.Как получить конкретную сериализацию RequestSecurityToken

Задача: части данных наших клиентов в нашей базе данных должны регулярно экспортироваться в базу данных, предоставляемую третьей стороной и доступную через веб-службу, которая, в свою очередь, защищена федерацией с помощью STS предоставленной четвертой стороной.

После нескольких часов, проведенных с запутанной документацией MSDN и множеством сообщений в блоге на WCF, я до сих пор не могу заставить 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> 

Согласно документации четвертого участника, СТС ожидает, что-то вроде этого:

<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 являются необязательными. Поэтому, насколько я вижу, у меня есть два вопроса:

  1. Как получить адрес AppliesTo для сериализации в качестве элемента URI?
  2. Как получить запрос на сериализацию как элементы атрибута/атрибута? (С правильным диалектом)?

Должен ли я реализовать некоторую пользовательскую сериализацию? Если да, то как и где я могу подключить его к фабрике/binding/request?

+0

Добро пожаловать на переполнение стека! Я редактировал ваш заголовок.Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

0
  1. Для работы с STS вы должны использовать WS2007HttpBinding вместо WSHttpBinding. Вы можете найти пример STS в WIF SDK. Он содержит пример с пользовательским токеном. Посмотрите here
  2. Попробуйте проблему безопасности без дополнительных параметров клиента. Создайте рабочее решение, которое просто выдаст токен и вызовет метод RP.
  3. Насколько я понимаю, вы хотите перейти к учетным записям пользовательского клиента STS PartnerId. В моем проекте я использую передачу пользовательских учетных данных через запрос AdditionalContext.

rst.AdditionalContext = new AdditionalContext(); rst.AdditionalContext.Items.Add (новый ContextItem (новый Uri («you_any_uri»), 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);    
    } 
} 
Смежные вопросы