在每次webservice调用之前调用某个方法

时间:2022-07-13 19:16:04

Here's the situation. I have a webservice (C# 2.0), which consists of (mainly) a class inheriting from System.Web.Services.WebService. It contains a few methods, which all need to call a method that checks if they're authorized or not.

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

Basically something like this (pardon the architecture, this is purely as an example):

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

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";
    }
}

As you can see, the method Validate has to be called in each method. I'm looking for a way to be able to call that method, while still being able to access the soap headers in a sane way. I've looked at the events in the global.asax, but I don't think I can access the headers in that class... Can I?

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

3 个解决方案

#1


9  

Here is what you need to do to get this to work correctly.

以下是您需要做的才能使其正常工作。

It is possible to create your own custom SoapHeader:

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

public class ServiceAuthHeader : SoapHeader
{
    public string SiteKey;
    public string Password;

    public ServiceAuthHeader() {}
}

Then you need a SoapExtensionAttribute:

然后你需要一个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;
        }
    }
}

And a custom SoapExtension:

和自定义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);
        }
    }
}

Then, in your web service add the following header to your method:

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

public ServiceAuthHeader AuthenticationSoapHeader;

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

When you consume this service, you must instantiate the custom header with the correct values and attach it to the request:

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

private ServiceAuthHeader header;
private PublicService ps;

header = new ServiceAuthHeader();
header.SiteKey = "Thekey";
header.Password = "Thepassword";
ps.ServiceAuthHeaderValue = header;

string WhatYouWant = ps.GetSomeStuffFromTheCloud(SomeId);

#2


1  

You can implement the so-called SOAP extension by deriving from SoapExtension base class. That way you will be able to inspect an incoming SOAP message and perform validate logic before a particular web method is called.

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

#3


1  

I'd take a look at adding a security aspect to the methods you're looking to secure. Take a look at PostSharp, and in particular the OnMethodBoundryAspect type, and OnEntry method.

我会看一下为您要保护的方法添加安全方面。看一下PostSharp,特别是OnMethodBoundryAspect类型和OnEntry方法。

#1


9  

Here is what you need to do to get this to work correctly.

以下是您需要做的才能使其正常工作。

It is possible to create your own custom SoapHeader:

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

public class ServiceAuthHeader : SoapHeader
{
    public string SiteKey;
    public string Password;

    public ServiceAuthHeader() {}
}

Then you need a SoapExtensionAttribute:

然后你需要一个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;
        }
    }
}

And a custom SoapExtension:

和自定义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);
        }
    }
}

Then, in your web service add the following header to your method:

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

public ServiceAuthHeader AuthenticationSoapHeader;

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

When you consume this service, you must instantiate the custom header with the correct values and attach it to the request:

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

private ServiceAuthHeader header;
private PublicService ps;

header = new ServiceAuthHeader();
header.SiteKey = "Thekey";
header.Password = "Thepassword";
ps.ServiceAuthHeaderValue = header;

string WhatYouWant = ps.GetSomeStuffFromTheCloud(SomeId);

#2


1  

You can implement the so-called SOAP extension by deriving from SoapExtension base class. That way you will be able to inspect an incoming SOAP message and perform validate logic before a particular web method is called.

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

#3


1  

I'd take a look at adding a security aspect to the methods you're looking to secure. Take a look at PostSharp, and in particular the OnMethodBoundryAspect type, and OnEntry method.

我会看一下为您要保护的方法添加安全方面。看一下PostSharp,特别是OnMethodBoundryAspect类型和OnEntry方法。