如何将标头中的用户名/密码传递给SOAP WCF服务

我正在尝试使用第三方Web服务https://staging.identitymanagement.lexisnexis.com/identity-proofing/services/identityProofingServiceWS/v2?wsdl

我已将其添加为服务引用,但我不确定如何传递标头的凭据。

如何使标头请求与此格式匹配?

   12345/userID password123 d+VxCZX1cH/ieMkKEr/ofA== 2012-08-04T20:25:04.038Z    

可能有一种更聪明的方法,但您可以手动添加标题,如下所示:

 var client = new IdentityProofingService.IdentityProofingWSClient(); using (new OperationContextScope(client.InnerChannel)) { OperationContext.Current.OutgoingMessageHeaders.Add( new SecurityHeader("UsernameToken-49", "12345/userID", "password123")); client.invokeIdentityService(new IdentityProofingRequest()); } 

在这里, SecurityHeader是一个自定义实现的类,由于我选择使用属性来配置XML序列化,因此需要一些其他类:

 public class SecurityHeader : MessageHeader { private readonly UsernameToken _usernameToken; public SecurityHeader(string id, string username, string password) { _usernameToken = new UsernameToken(id, username, password); } 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"; } } protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) { XmlSerializer serializer = new XmlSerializer(typeof(UsernameToken)); serializer.Serialize(writer, _usernameToken); } } [XmlRoot(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")] public class UsernameToken { public UsernameToken() { } public UsernameToken(string id, string username, string password) { Id = id; Username = username; Password = new Password() {Value = password}; } [XmlAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")] public string Id { get; set; } [XmlElement] public string Username { get; set; } [XmlElement] public Password Password { get; set; } } public class Password { public Password() { Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"; } [XmlAttribute] public string Type { get; set; } [XmlText] public string Value { get; set; } } 

我没有将Nonce位添加到UsernameToken XML,但它与Password one非常相似。 还需要添加Created元素,但这是一个简单的[XmlElement]

上面的答案是错的! 不要添加自定义标题。 从您的示例x​​ml判断,它是标准的WS-Security标头。 WCF绝对支持开箱即用。 添加服务引用时,应在配置文件中为您创建basicHttpBinding绑定。 您必须修改它以包含具有TransportWithMessageCredential模式的security元素和包含clientCredentialType = UserName的message元素:

        

上面的配置告诉WCF通过HTTPS在SOAP头中期望用户ID /密码。 然后,您可以在拨打电话之前在代码中设置ID /密码:

 var service = new MyServiceClient(); service.ClientCredentials.UserName.UserName = "username"; service.ClientCredentials.UserName.Password = "password"; 

除非此特定服务提供商偏离标准,否则它应该有效。

添加自定义硬编码标头可能会起作用(有时也可能会被拒绝),但完全是错误的方法。 WSSE的目的是安全性。 出于这个原因,Microsoft发布了Microsoft Web Services Enhancements 2.0以及随后的WSE 3.0。 您需要安装此软件包( http://www.microsoft.com/en-us/download/details.aspx?id=14089 )。

文档不容易理解,特别是对于那些没有使用过SOAP和WS-Addressing的人。 首先,“BasicHttpBinding”是Soap 1.1,它不会给你与WSHttpBinding相同的消息头。 安装包并查看示例。 您需要从WSE 3.0引用DLL,您还需要正确设置消息。 WS Addressing标头上有大量或多种变体。 您要查找的是UsernameToken配置。

这是一个较长的解释,我应该为每个人写一些东西,因为我无法在任何地方找到正确的答案。 至少您需要从WSE 3.0包开始。

假设您在web.config中有名称localhost服务引用,那么您可以按如下方式进行操作

 localhost.Service objWebService = newlocalhost.Service(); localhost.AuthSoapHd objAuthSoapHeader = newlocalhost.AuthSoapHd(); string strUsrName =ConfigurationManager.AppSettings["UserName"]; string strPassword =ConfigurationManager.AppSettings["Password"]; objAuthSoapHeader.strUserName = strUsrName; objAuthSoapHeader.strPassword = strPassword; objWebService.AuthSoapHdValue =objAuthSoapHeader; string str = objWebService.HelloWorld(); Response.Write(str); 

假设您使用HttpWebRequest和HttpWebResponse调用Web服务,因为.Net客户端doest支持您尝试使用的WSLD结构。

在这种情况下,您可以在标题上添加安全凭证,如:

   YOU_USERNAME/wsse:Username>YOU_PASSWORD3WSOKcKKm0jdi3943ts1AQ==2015-01-12T16:46:58.386Z     

您可以使用SOAPUI来使用http日志获取wsse安全性。

要小心,因为它不是一个安全的方案。

我从这里得到了一个更好的方法: WCF:创建自定义标题,如何添加和使用这些标题

客户识别自己
这里的目标是让客户端提供某种信息,服务器可以使用这些信息来确定发送消息的人。 以下C#代码将添加名为ClientId的标头:

 var cl = new ActiveDirectoryClient(); var eab = new EndpointAddressBuilder(cl.Endpoint.Address); eab.Headers.Add( AddressHeader.CreateAddressHeader("ClientId", // Header Name string.Empty, // Namespace "OmegaClient")); // Header Value cl.Endpoint.Address = eab.ToEndpointAddress(); // Now do an operation provided by the service. cl.ProcessInfo("ABC"); 

该代码正在做的是添加名为ClientId的端点头,其值为OmegaClient,以插入到没有命名空间的soap头中。

客户端配置文件中的自定义标头
还有另一种方法可以执行自定义标头。 这可以在客户端的Xml配置文件中实现,其中通过将自定义头指定为端点的一部分来发送所有消息,如下所示:

              Console_Client      

显然,这篇文章已经存在多年了 – 但事实是我在寻找类似问题时确实找到了它。 在我们的例子中,我们必须将用户名/密码信息添加到Security标头中。 这与在Security标头之外添加标头信息不同。

执行此操作的正确方法(对于自定义绑定/ authenticationMode =“CertificateOverTransport”)(如.Net框架版本4.6.1),是照常添加客户端凭据:

  client.ClientCredentials.UserName.UserName = "[username]"; client.ClientCredentials.UserName.Password = "[password]"; 

然后在安全绑定元素中添加“标记” – 因为当身份validation模式设置为证书时,默认情况下不会包含用户名/密码凭据。

您可以像这样设置此令牌:

  //Get the current binding System.ServiceModel.Channels.Binding binding = client.Endpoint.Binding; //Get the binding elements BindingElementCollection elements = binding.CreateBindingElements(); //Locate the Security binding element SecurityBindingElement security = elements.Find(); //This should not be null - as we are using Certificate authentication anyway if (security != null) { UserNameSecurityTokenParameters uTokenParams = new UserNameSecurityTokenParameters(); uTokenParams.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient; security.EndpointSupportingTokenParameters.SignedEncrypted.Add(uTokenParams); } client.Endpoint.Binding = new CustomBinding(elements.ToArray()); 

应该这样做。 如果没有上述代码(显式添加用户名令牌),即使在客户端凭据中设置用户名信息,也可能无法将这些凭据传递给服务。