【问题标题】:Call a certain method before each webservice call在每次 webservice 调用之前调用某个方法
【发布时间】:2008-09-24 22:50:31
【问题描述】:

情况是这样的。我有一个 web 服务(C# 2.0),它(主要)由一个继承自 System.Web.Services.WebService 的类组成。它包含一些方法,它们都需要调用一个方法来检查它们是否被授权。

基本上是这样的(请原谅架构,这纯粹是一个例子):

public class ProductService : WebService
{
    public AuthHeader AuthenticationHeader;

    [WebMethod(Description="Returns true")]
    [SoapHeader("AuthenticationHeader")]        
    public bool MethodWhichReturnsTrue()
    {
        if(Validate(AuthenticationHeader))
        {
            throw new SecurityException("Access Denied");
        }
        return true;
    }

    [WebMethod(Description="Returns false")]
    [SoapHeader("AuthenticationHeader")]        
    public bool MethodWhichReturnsFalse()
    {
        if(Validate(AuthenticationHeader))
        {
            throw new SecurityException("Access Denied");
        }
        return false;
    }

    private bool Validate(AuthHeader authHeader)
    {
        return authHeader.Username == "gooduser" && authHeader.Password == "goodpassword";
    }
}

如您所见,方法Validate 必须在每个方法中调用。我正在寻找一种能够调用该方法的方法,同时仍然能够以理智的方式访问肥皂标题。我查看了global.asax 中的事件,但我认为我无法访问该类中的标题...可以吗?

【问题讨论】:

    标签: c# .net web-services


    【解决方案1】:

    您需要执行以下操作才能使其正常工作。

    可以创建自己的自定义 SoapHeader:

    public class ServiceAuthHeader : SoapHeader
    {
        public string SiteKey;
        public string Password;
    
        public ServiceAuthHeader() {}
    }
    

    那么你需要一个 SoapExtensionAttribute:

    public class AuthenticationSoapExtensionAttribute : SoapExtensionAttribute
    {
        private int priority;
    
        public AuthenticationSoapExtensionAttribute()
        {
        }
    
        public override Type ExtensionType
        {
            get
            {
                return typeof(AuthenticationSoapExtension);
            }
        }
    
        public override int Priority
        {
            get
            {
                return priority;
            }
            set
            {
                priority = value;
            }
        }
    }
    

    还有一个自定义的 SoapExtension:

    public class AuthenticationSoapExtension : SoapExtension
    {
        private ServiceAuthHeader authHeader;
    
        public AuthenticationSoapExtension()
        {
        }
    
        public override object GetInitializer(Type serviceType)
        {
            return null;
        }
    
        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return null;
        }
    
        public override void Initialize(object initializer)
        {        
        }
    
        public override void ProcessMessage(SoapMessage message)
        {
            if (message.Stage == SoapMessageStage.AfterDeserialize)
            {
                foreach (SoapHeader header in message.Headers)
                {
                    if (header is ServiceAuthHeader)
                    {
                        authHeader = (ServiceAuthHeader)header;
    
                        if(authHeader.Password == TheCorrectUserPassword)
                        {
                            return;  //confirmed
                        }
                    }
                }
    
                throw new SoapException("Unauthorized", SoapException.ClientFaultCode);
            }
        }
    }
    

    然后,在您的网络服务中将以下标头添加到您的方法中:

    public ServiceAuthHeader AuthenticationSoapHeader;
    
    [WebMethod]
    [SoapHeader("AuthenticationSoapHeader")]
    [AuthenticationSoapExtension]
    public string GetSomeStuffFromTheCloud(string IdOfWhatYouWant)
    {
      return WhatYouWant;
    }
    

    当您使用此服务时,您必须使用正确的值实例化自定义标头并将其附加到请求中:

    private ServiceAuthHeader header;
    private PublicService ps;
    
    header = new ServiceAuthHeader();
    header.SiteKey = "Thekey";
    header.Password = "Thepassword";
    ps.ServiceAuthHeaderValue = header;
    
    string WhatYouWant = ps.GetSomeStuffFromTheCloud(SomeId);
    

    【讨论】:

    • 不像我想象的那么简单。现在就试试这个。
    • 有效!请记住,Visual Studio 基于 Web 的访问不会触发扩展,因为它不使用 SOAP 来发出请求。让我挠了几分钟。
    【解决方案2】:

    您可以通过从SoapExtension base 类派生来实现所谓的SOAP 扩展。这样,您将能够检查传入的 SOAP 消息并在调用特定 Web 方法之前执行验证逻辑。

    【讨论】:

      【解决方案3】:

      我会考虑为您要保护的方法添加安全方面。看看PostSharp,尤其是 OnMethodBoundryAspect 类型和 OnEntry 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 2016-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多