2014-09-10 44 views
2

目标是通过使用WCF连接到Web服务,该Web服务需要标准中指定的UserNameToken ws-security “绿洲-200401-WSS-皂消息的安全-1.0”。WCF - 使用时间戳和密码摘要为oasis-200401-wss-username-token-profile-1.0创建UserNameToken

规格齐全都可以在这里找到http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf

有如何创建令牌并没有为我工作的几个例子。 当我发布这个我已经找到答案,但因为这并不容易,我让我在这里找到解决方案,并希望它可以得到改善。所以我会跳到答案。

回答

3
using System; 
using System.Collections.Generic; 
using System.IdentityModel.Tokens; 
using System.Security.Cryptography; 
using System.ServiceModel; 
using System.ServiceModel.Description; 
using System.ServiceModel.Security; 
using System.ServiceModel.Channels; 

using System.Text; 
using System.Threading.Tasks; 

namespace WSClient 
{ 

    //Create this custom credentials class to implement UserNameToken autentication 
    public class CustomCredentials : ClientCredentials 
    { 
     public CustomCredentials() 
     { } 

     protected CustomCredentials(CustomCredentials cc) 
      : base(cc) 
     { } 

     public override System.IdentityModel.Selectors.SecurityTokenManager CreateSecurityTokenManager() 
     { 
      return new CustomSecurityTokenManager(this); 
     } 

     protected override ClientCredentials CloneCore() 
     { 
      return new CustomCredentials(this); 
     } 
    } 

    public class CustomSecurityTokenManager : ClientCredentialsSecurityTokenManager 
    { 
     public CustomSecurityTokenManager(CustomCredentials cred) 
      : base(cred) 
     { } 

     public override System.IdentityModel.Selectors.SecurityTokenSerializer CreateSecurityTokenSerializer(System.IdentityModel.Selectors.SecurityTokenVersion version) 
     { 
      return new CustomTokenSerializer(System.ServiceModel.Security.SecurityVersion.WSSecurity10); 
     } 
    } 

    public class CustomTokenSerializer : WSSecurityTokenSerializer 
    { 
     public CustomTokenSerializer(SecurityVersion sv) 
      : base(sv) 
     { } 


     protected override void WriteTokenCore(System.Xml.XmlWriter writer, 
             System.IdentityModel.Tokens.SecurityToken token) 
     { 

      UserNameSecurityToken userToken = token as UserNameSecurityToken; 

      string tokennamespace = "o"; 

      DateTime created = DateTime.UtcNow; 
      string createdStr = created.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); 

      string phrase = Guid.NewGuid().ToString(); 
      var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(phrase));         
      SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider(); 

      //Password_Digest = Base64 (SHA-1 (nonce + created + password)) 
      string Password_Digest = Convert.ToBase64String(sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase + createdStr + userToken.Password))); // pxLqPLCXU1EiUS+NnpRuCw== 
      var stringToWrite = string.Format(
       "<{0}:UsernameToken u:Id=\"" + token.Id + 
       "\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" + 
       "<{0}:Username>" + userToken.UserName + "</{0}:Username>" + 
       "<{0}:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + 
       Password_Digest + "</{0}:Password>" + 
       "<{0}:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + 
       nonce + "</{0}:Nonce>" + 
       "<u:Created>" + createdStr + "</u:Created></{0}:UsernameToken>", tokennamespace); 

      writer.WriteRaw(stringToWrite); 
     } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
      //for invalid ssl server certificate 
       System.Net.ServicePointManager.ServerCertificateValidationCallback += 
(se, cert, chain, sslerror) => 
{ 
    return true; 
}; 

       CustomBinding binding = new CustomBinding(); 

       var security = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement(); 
       security.IncludeTimestamp = true; 
       security.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256; 
       security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10; 
       security.EnableUnsecuredResponse = true; 

       var encoding = new TextMessageEncodingBindingElement(); 
       encoding.MessageVersion = MessageVersion.Soap11; 
       var transport = new HttpsTransportBindingElement(); 
       transport.MaxReceivedMessageSize = 2000000; 

       binding.Elements.Add(security); 
       binding.Elements.Add(encoding); 
       binding.Elements.Add(transport); 

       WSClient.Proxy.TargetWS client = new Proxy.TargetWS(binding, 
        new EndpointAddress(Properties.Settings.Default.Url)); 

       //change credential for the custom credentials instance 
       client.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>(); 
       client.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials()); 

       client.ClientCredentials.UserName.UserName = Properties.Settings.Default.username; 
       client.ClientCredentials.UserName.Password = Properties.Settings.Default.password; 


       Proxy.Message message = new WSClient.Proxy.Message(); 
       message.id = "whatever"; 
       client.foo(message); 

       System.Console.Write("Success"); 
      } 
      catch (Exception ex) 
      { 
       System.Console.Write(ex.Message); 
      } 

     } 
    } 
} 

有点广泛!

本质上,需要根据Oasys规范序列化令牌。为此,需要按照提供的方式派生ClientCredentials,ClientCredentialsSecurityTokenManager和WSSecurityTokenSerializer。

关于绑定,不知道是否适用于所有或者如果规范允许变化。