c# - metodo - Llame a un método determinado antes de cada llamada al servicio web
httpwebrequest call web service c# (3)
Aquí está la situación. Tengo un servicio web (C # 2.0), que consiste en (principalmente) una clase que hereda de System.Web.Services.WebService. Contiene algunos métodos, que todos necesitan llamar a un método que verifica si están autorizados o no.
Básicamente algo como esto (perdón por la arquitectura, esto es puramente como un ejemplo):
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";
}
}
Como puede ver, el método Validate
debe Validate
en cada método. Estoy buscando una manera de poder llamar a ese método, mientras sigo siendo capaz de acceder a los encabezados de jabón de una manera sensata. He visto los eventos en el global.asax
, pero no creo que pueda acceder a los encabezados de esa clase ... ¿Puedo?
Esto es lo que debe hacer para que esto funcione correctamente.
Es posible crear su propio SoapHeader personalizado:
public class ServiceAuthHeader : SoapHeader
{
public string SiteKey;
public string Password;
public ServiceAuthHeader() {}
}
Entonces necesitas un 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;
}
}
}
Y una SoapExtension personalizada:
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);
}
}
}
Luego, en su servicio web, agregue el siguiente encabezado a su método:
public ServiceAuthHeader AuthenticationSoapHeader;
[WebMethod]
[SoapHeader("AuthenticationSoapHeader")]
[AuthenticationSoapExtension]
public string GetSomeStuffFromTheCloud(string IdOfWhatYouWant)
{
return WhatYouWant;
}
Cuando consume este servicio, debe crear una instancia del encabezado personalizado con los valores correctos y adjuntarlo a la solicitud:
private ServiceAuthHeader header;
private PublicService ps;
header = new ServiceAuthHeader();
header.SiteKey = "Thekey";
header.Password = "Thepassword";
ps.ServiceAuthHeaderValue = header;
string WhatYouWant = ps.GetSomeStuffFromTheCloud(SomeId);
Puede implementar la llamada extensión SOAP derivando de la clase base SoapExtension . De esta forma, podrá inspeccionar un mensaje SOAP entrante y ejecutar la lógica de validación antes de que se llame a un método web particular.
Echaré un vistazo para agregar un aspecto de seguridad a los métodos que está buscando proteger. Eche un vistazo a PostSharp , y en particular al tipo OnMethodBoundryAspect y al método OnEntry.