2008-09-24 4 views
7

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

ответ

9

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

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

Не так прямолинейно, как я предполагал. Попытаемся попробовать это сейчас. – 2008-09-25 08:58:35

1

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

1

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

Смежные вопросы