WCF-为oasis-200401-wss-username-token-profile-1.0创建带有时间戳和密码摘要的UserNameToken [英] WCF - create UserNameToken with timestamp and password digest for oasis-200401-wss-username-token-profile-1.0

查看:32
本文介绍了WCF-为oasis-200401-wss-username-token-profile-1.0创建带有时间戳和密码摘要的UserNameToken的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是通过使用WCF,连接到需要UserNameToken ws-security(如标准"oasis-200401-wss-soap-message-security-1.0"所指定)的Web服务.

The objective is, by using WCF, connect to a Web service that requires UserNameToken ws-security as specified by the standard "oasis-200401-wss-soap-message-security-1.0".

完整的规范可以在这里找到 http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf

Full specification can be find here http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf

关于如何创建令牌的示例很少,但没有一个对我有用.当我发布此消息时,我已经找到了答案,但是由于这并不容易,因此我将找到的解决方案放在这里,并希望可以对其进行改进.所以我将跳到答案.

There are few examples of how to create the token and none worked for me. When i posted this i had already found the answer but since it was not easy, i let here the solution i found and hope it can be improved. So i will just jump to the answer.

推荐答案

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.

Essentially, it is need to serialize the token according to Oasys specifications. To do this it is need to derivate ClientCredentials, ClientCredentialsSecurityTokenManager and WSSecurityTokenSerializer in the way presented.

关于绑定,不确定是否适用于所有绑定或规范是否允许变更.

About the binding, not sure if works for all or if variations are allowed by the specification.

这篇关于WCF-为oasis-200401-wss-username-token-profile-1.0创建带有时间戳和密码摘要的UserNameToken的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆