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

标签 c# .net web-services

情况是这样的。我有一个 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。我正在寻找一种能够调用该方法的方法,同时仍然能够以理智的方式访问 soap header 。我查看了 global.asax 中的事件,但我认为我无法访问该类中的 header ...可以吗?

最佳答案

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

可以创建您自己的自定义 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);
        }
    }
}

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

public ServiceAuthHeader AuthenticationSoapHeader;

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

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

private ServiceAuthHeader header;
private PublicService ps;

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

string WhatYouWant = ps.GetSomeStuffFromTheCloud(SomeId);

关于c# - 在每次webservice调用之前调用某个方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/130427/

相关文章:

c# - 最佳并行下载文件数

c# - MVC + WCF + TDD 或 DDD 架构

C# Azure Function App 部署时的行为有所不同

c# - 在没有 wsdl 的情况下调用 web 服务和反序列化 soap

c# - 将表名作为参数传递给 MySqlCommand 时出现 MySqlException

c# - 用于删除文字格式的正则表达式模式

c# - 如何在 C# 中创建具有到期日期的用户密码

c# - 文本框是否将全数字文本保存为长文本或字符串?

web-services - WSDL、DISCO 和 EVENT 之间有什么区别?

java - SOAP 客户端 - ProtocolException : Server redirected too many times