如何在WCF中为soap消息添加安全标头,

时间:2015-06-01 08:16:32

标签: c# wcf soap

我正在尝试在WCF中添加SOAP安全头用户名令牌,对不起,我已经在上一篇文章中发布了我的所有路径,但得到了更多方法并在此处添加可能它可能有效。现在我得到一个例外

  

"无法拨打' WriteEndElement'而深度是' 0'。"

   using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3;
//using CustomAssertion.ServiceReference1;

namespace test
{

    public class InspectorBehavior : IEndpointBehavior
    {
        public ClientInspector ClientInspector { get; set; }
        public InspectorBehavior(ClientInspector clientInspector)
        {
            ClientInspector = clientInspector;
        }
        public void Validate(ServiceEndpoint endpoint)
        { }
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        { }
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            if (this.ClientInspector == null) throw new InvalidOperationException("Caller must supply ClientInspector.");
            clientRuntime.MessageInspectors.Add(ClientInspector);
        }
    }

    public class ClientInspector : IClientMessageInspector
    {
        public MessageHeader[] Headers { get; set; }
        public ClientInspector(params MessageHeader[] headers)
        {
            Headers = headers;
        }
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            if (Headers != null)
            {
                for (int i = Headers.Length - 1; i >= 0; i--)
                    request.Headers.Insert(0, Headers[i]);
            }
            return request;
        }
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
        }
    }

    public class SecurityHeader : MessageHeader
    {
        public string SystemUser { get; set; }
        public string SystemPassword { get; set; }
        public SecurityHeader(string systemUser, string systemPassword)
        {
            SystemUser = systemUser;
            SystemPassword = systemPassword;
        }
        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 OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            writer.WriteStartElement("wsse", Name, Namespace);
            writer.WriteXmlnsAttribute("wsse", Namespace);
        }
        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            var nonce = new byte[64];
            RandomNumberGenerator.Create().GetBytes(nonce);
            string created = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ss.msZ");
            writer.WriteStartElement("wsse", "UsernameToken", Namespace);
            writer.WriteXmlnsAttribute("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
            writer.WriteValue(SystemUser);
            //writer.WriteStartElement("wsse", "Username", null);
            //writer.WriteString(SystemUser);
            writer.WriteEndElement();//End Username 

            writer.WriteStartElement("wsse", "Password", Namespace);
            //writer.WriteStartElement("wsse", "Password", null);
            writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
            writer.WriteValue(ComputePasswordDigest(SystemPassword, nonce, created));
            //writer.WriteString(ComputePasswordDigest(SystemPassword, nonce, created));
            writer.WriteEndElement();//End Password 

            writer.WriteStartElement("wsse", "Nonce", null);
            writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
            writer.WriteBase64(nonce, 0, nonce.Length);
            writer.WriteEndElement();//End Nonce 

            // writer.WriteStartElement("wsse", "Created", null);
            // writer.WriteString(created);
            // writer.WriteEndElement();//End Created 
            // writer.WriteEndElement();//End UsernameToken

            writer.Flush();
        }
        private string ComputePasswordDigest(string secret, byte[] nonceInBytes, string created)
        {
            byte[] createdInBytes = Encoding.UTF8.GetBytes(created);
            byte[] secretInBytes = Encoding.UTF8.GetBytes(secret);
            byte[] concatenation = new byte[nonceInBytes.Length + createdInBytes.Length + secretInBytes.Length];
            Array.Copy(nonceInBytes, concatenation, nonceInBytes.Length);
            Array.Copy(createdInBytes, 0, concatenation, nonceInBytes.Length, createdInBytes.Length);
            Array.Copy(secretInBytes, 0, concatenation, (nonceInBytes.Length + createdInBytes.Length), secretInBytes.Length);
            return Convert.ToBase64String(SHA1.Create().ComputeHash(concatenation));
        }
    }
    public class Service1 : IService1
    {

        public string security(int a)
        {
            ServiceReference1.Service1Client action = new ServiceReference1.Service1Client();
            action.Endpoint.Behaviors.Add(new InspectorBehavior(
            new ClientInspector(new SecurityHeader("username", "password"))));
            return action.GetData(8);
        }

    }
}

如果我需要添加,等待专家的回复,请建议任何其他方案。

0 个答案:

没有答案