2009-04-09 17 views
8

Sono abbiamo vicino a nessuno esperienza con il protocollo SOAP. Il servizio ho bisogno di connettermi all'intestazione richiesta. Penso che questo sia piuttosto standard in Java, ma in C# è necessario creare questa intestazione a mano.Clueless su come creare SOAP <wsse: Sicurezza> intestazione

Qualcuno qui stato in grado di connettersi al servizio simile: hanno creato l'intestazione o forse anche conoscere alcuni libreria standard che semplificherebbe creazione di intestazione? Puoi condividere qualche codice o riferimenti?

Ho anche trovato un indizio che forse intestazione verrà generato se si utilizza WS2005, perché non v'è WS3 componente aggiuntivo per esso. Qualcuno può commentare questo? Dopo una rapida occhiata a questo addin ho trovato campi simili come nell'intestazione di sicurezza, ma ancora non ero in grado di creare l'intestazione.

risposta

6

Divertente dovresti dirlo - ultimamente ho fatto esattamente.

sono riuscito a farlo utilizzando una SoapExtension che utilizza ChainStream per mantenere una copia del flusso originale, solo le copie del torrente durante BeforeDeserialize e aggiunge l'intestazione durante AfterSerialize.

L'aggiunta dell'intestazione è un caso di lettura del contenuto del "nuovo" flusso (restituito da ChainStream) in un documento XML (XDocument nel mio caso), aggiunta dell'intestazione e quindi scritta nel flusso originale passato in ChainStream.

Purtroppo questo è piuttosto sporca, e non è possibile (per quanto io sappia) utilizzare una nuova istanza con le informazioni di autenticazione appropriato quando è necessario.

Ho più del modo in cui si utilizza un SoapHeader invece, l'aggiunta di un attributo appropriato per ciascun metodo del servizio Web e anche un adeguato campo/proprietà con un'istanza dell'intestazione richiesta - ma la serializzazione SOAP è attualmente mi dà mal di testa in termini di specificare i nomi degli elementi giusti (con namespace). È qualcosa che ho intenzione di chiedere ad altri quando ho tempo.

Mi spiace di non essere in grado di darti una risposta completa - e mi scuso anche per la mancanza di codice, appartiene alla società piuttosto che a me - ma spero che almeno ti dia un punto di partenza.

+1

downvoters: Si prega di motivare ... –

4

è generalmente molto facile aggiungere un'intestazione SOAP al vostro proxy web serivce in .Net. Ecco un esempio di codice veloce.

Creare un nuovo header SOAP

using System.Web.Services.Protocols; 

public class SoapAuthHeader : SoapHeader 
{ 
public string Username; 
public string Password; 
} 

Nel vostro web classe di servizio di proxy:

public class MyWebServicesProxy : System.Web.Services.Protocols.SoapHttpClientProtocol { 

    public SoapAuthHeader AuthHeader; 

    ... 

} 

E poi usare:

SoapAuthHeader authHeader = new SoapAuthHeader(); 
authHeader.Username = "username"; 
authHeader.Password = "password"; 

MyWebServicesProxy myProxy = new MyWebServicesProxy(); 
myProxy.AuthHeader = authHeader; 

Edit: Ci sono altri modi per questo e Microsoft ha un WSE library che include WS-Security che offre molta più funzionalità il semplice esempio sopra. Se hai bisogno di token Kerberos o firma del certificato nella tua intestazione SOAP, allora è la strada da percorrere. se è necessario aggiungere un nome utente e una password semplici per un servizio Web che funziona su SSL, l'exmaple potrebbe essere tutto ciò che serve.

Edit: Blurb rapido sul WSE All'inizio di questo decennio, quando i servizi web stavano per conquistare il mondo un gruppo di operatori del settore (Microsoft, IBM, Sun ecc) si sono riuniti a venire con modi standard di fare le cose sopra di loro. Il corpo formato era OASIS. Da allora Microsoft ha rilasciato diverse versioni della sua libreria WSE per supportare alcune delle specifiche, ma non sono mai state incorporate nel framework .Net anche se la prima versione è stata resa pubblica intorno al 2003.

Servizi Web mentre ancora molto popolare e, a mio parere, un ottimo modo per integrare tra le diverse applicazioni Internet è andato un po 'a disagio. Uno dei motivi è senza dubbio perché AJAX e i servizi web non erano i migliori tra i compagni di letto, anche se questo è migliorato. Anche i servizi Web diventano piuttosto complicati una volta che si iniziano a includere tutte le specifiche aggiuntive di sWSE e uno dei servizi web di thinge che è stato risolto è la complessità in altri protocolli RPC, CORBA, ecc. Nel frattempo REST ha guadagnato molta popolarità a spese dei servizi Web e delle librerie AJAX lo preferiscono spesso.

I servizi Web non spariranno presto con qualsiasi mezzo, ma probabilmente non lo faranno presto.

+3

WSE non funziona per Visual Studio 2008, per quanto io sappia, che è davvero fastidioso. La via di SoapHeader è carina in teoria, ma nel mio caso * particolare * ho un problema nel trovare il giusto spazio dei nomi per gli elementi all'interno dell'intestazione :( –

+0

@Jon: è un vero peccato. Ho avuto occasione in passato dover approfondire le catene di serializzazione Remoting e SOAP e mentre non è proibitivamente difficile, non è sicuramente elegante come creare intestazioni personalizzate o WSE. – sipwiz

+1

Giusto per mettere in chiaro - Sono per gli elementi che sono i miei tipi, dove Posso usare SoapTypeAttribute e specificare il nome/spazio dei nomi lì.È la mancanza di una proprietà dello spazio dei nomi in SoapElementAttribute che mi sta mordendo :( –

8

Siamo stati in grado di risolverlo con il seguente codice:

public class SecurityHeader : System.ServiceModel.Channels.MessageHeader { 
    public string userName; 
    public string password; 

    protected override void OnWriteStartHeader (System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion) 
    { 
     writer.WriteStartElement("wsse", Name, Namespace); 
     writer.WriteXmlnsAttribute("wsse", Namespace); 
    } 

    protected override void OnWriteHeaderContents (System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion) 
    { 
     writer.WriteStartElement("wsse", "UsernameToken", Namespace); 

     writer.WriteStartElement("wsse", "Username", Namespace); 
     writer.WriteValue(userName); 
     writer.WriteEndElement(); 

     writer.WriteStartElement("wsse", "Password", Namespace); 
     writer.WriteValue(password); 
     writer.WriteEndElement(); 

     writer.WriteEndElement(); 

    } 

    public override string Name 
    { 
     get { return "Security"; } 
    } 

    public override string Namespace 
    { 
     get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; } 
    } 
} 

Questo ha scritto l'intestazione che è stato richiesto dalla scatola DataPower.

come utilizzare la classe di SecurityHeader

public static void Main(string[] args) 
    { 

     var webService = new ServiceReference1.MyWebService(); 
     .... 
     webService.Open(); 


     using (OperationContextScope scope = new OperationContextScope((IContextChannel)webService.InnerChannel)) 
     { 

      var myObjRequest = GetMyObjRequest(); 

      MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders; 
      messageHeadersElement.Add(SecurityHeader("UserName", "Password")) 


      var res = webService.MyServe(myObjRequest); 
      Console.WriteLine(res.ToString()); 
     } 
    } 
+0

Amico, ti amo! Ho usato il tuo codice e ha funzionato! Mi stavo integrando con "oracle on demand crm".Ho appena dovuto aggiungere questa riga dopo la "Password" StartElement: 'writer.WriteAttributeString (" Tipo "," http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss- username-token-profile-1.0 # PasswordText ");' Grazie! –

Problemi correlati