Вызов определенного метода перед каждым вызовом веб-сервиса

Вот такая ситуация. У меня есть веб-сервис (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, но не думаю, что могу получить доступ к заголовкам в этом классе ... Можно?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
4 865
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете реализовать так называемое расширение SOAP, унаследовав его от класса База SoapExtension. Таким образом, вы сможете проверить входящее сообщение SOAP и выполнить логику проверки перед вызовом определенного веб-метода.

Ответ принят как подходящий

Вот что вам нужно сделать, чтобы это работало правильно.

Можно создать свой собственный 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);

Не так просто, как я предполагал. Сейчас попробую.

Erik van Brakel 25.09.2008 12:58

Оно работает! Имейте в виду, что веб-доступ к Visual Studio не запускает расширение, так как он не использует протокол SOAP для выполнения запроса. Я несколько минут почесал затылок.

Erik van Brakel 25.09.2008 15:48

Я бы посмотрел на добавление аспекта безопасности к методам, которые вы хотите защитить. Взгляните на PostSharp и, в частности, на тип OnMethodBoundryAspect и метод OnEntry.

Другие вопросы по теме