| Gustavo's profileGustavo BonanseaBlogLists | Help |
|
July 06 Seguridad: Autenticación de usuarios en un Web ServiceEl objetivo de esta pequeña contribución en el blog es el de explicar cómo realizar un web service que autentique el usuario utilizando Headers Soap.
Existen varios modos de proveer autenticación para un webservice. Vamos a identificar alguno de ellos y luego veremos en mayor detalle la utilización de headers soap.
1) Se puede proveer de seguridad integrada, agregando entradas al archivo web.config
Para utilizar seguridad integrada se debe deshabilitar el acceso anónimo y modificar el web.config del webservice para agregarle los siguientes nodos
<authentication mode="Windows" />
<identity impersonate="true" /> <authorization>
<deny user="DomainName\UserName" /> <allow roles="DomainName\WindowsGroup" /> </authorization> Agregando nodos "deny" o "allow" se puede denegar o permitir el acceso a determinados usuarios o grupos.
Suponiendo que SecureWebService es el webservice que se desea ejecutar, necesitamos pasarle las credenciales necesarias para ejecutarlo:
Dim ServiceToCall As New SecureService.SecureWebService ServiceToCall.Credentials = New System.Net.NetworkCredential("user", "pwd") Para más información sobre este tema: leer. 2) Pueden utilizarse las extensiones para Web Services WS-E que pertimen desarrollar web services seguros utilizando los últimos estándares de seguridad. Es la forma más completa y aconsejable a nivel de arquitectura.
Para leer más:
3) Utilizar headers soap para pasarle información del usuario al webservice.
Este es el punto que nos interesa.
Lo primero que haremos es crear una clase AuthenticationHeader que deriva de SoapHeader. Esta clase representa el Header Soap que contiene la información del usuario que será provista por el cliente del web service y que verificaremos en el mismo para autenticar la identidad del usuario.
Imports System.Web.Services.Protocols '''----------------------------------------------------------------------------- ''' Project : SecureWebService ''' Class : AuthenticationHeader ''' '''----------------------------------------------------------------------------- ''' <summary> ''' Header Soap para autenticacion del usuario ''' </summary> ''' <remarks></remarks> '''----------------------------------------------------------------------------- Public Class AuthenticationHeader Inherits SoapHeader
Private _UserName As String Private _Password As String
Public Property UserName() As String Get Return _UserName End Get Set(ByVal Value As String) _UserName = Value End Set End Property
Public Property Password() As String Get Return _Password End Get Set(ByVal Value As String) _Password = Value End Set End Property
End Class
Luego creamos una clase que derive de WebService que va a ser una versión especializada de web service con contiene un header con la información del usuario.
'''----------------------------------------------------------------------------- ''' Project : SecureWebService ''' Class : SecureService ''' '''----------------------------------------------------------------------------- ''' <summary> ''' Web service con autenticacion ''' </summary> ''' <remarks></remarks> '''----------------------------------------------------------------------------- Public Class SecureService Inherits WebService
Public AuthenticationCredentials As AuthenticationHeader
End Class
Luego agregamos un web service que en este caso llamaremos SecureWebService.asmx. Una vez agregado cambiaremos la herencia del mismo, en vez de derivar directamente de la clase WebService lo haremos derivar de la clase SecureService que creamos anteriormente (recordar que ésta deriva de WebService e incluye el header con la autenticación). Imports System.Web.Services.Protocols Imports System.Web.Services
<System.Web.Services.WebService(Namespace:="http://tempuri.org/SecureWebService/SecureWebService")> _ Public Class SecureWebService Inherits SecureService
#Region " Web Services Designer Generated Code "
Public Sub New() MyBase.New()
'This call is required by the Web Services Designer. InitializeComponent()
'Add your own initialization code after the InitializeComponent() call
End Sub
'Required by the Web Services Designer Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Web Services Designer 'It can be modified using the Web Services Designer. 'Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() components = New System.ComponentModel.Container End Sub
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) 'CODEGEN: This procedure is required by the Web Services Designer 'Do not modify it using the code editor. If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub
#End Region
' WEB SERVICE EXAMPLE ' The HelloWorld() example service returns the string Hello World. ' To build, uncomment the following lines then save and build the project. ' To test this web service, ensure that the .asmx file is the start page ' and press F5. ' <WebMethod(), SoapHeader("AuthenticationCredentials")> _ Public Function SecureWebMethod() As String If UserHasPermission(AuthenticationCredentials) Then Return "El servicio se ejecutó con éxito" Else Return "El usuario no tiene permisos para realizar la operación solicitada" End If End Function
'''----------------------------------------------------------------------------- ''' <summary> ''' Verifica la identidad y permisos del usuario ''' </summary> ''' <param name="value"></param> ''' <returns></returns> ''' <remarks></remarks> '''----------------------------------------------------------------------------- Private Function UserHasPermission(ByVal value As AuthenticationHeader) As Boolean If AuthenticationCredentials Is Nothing Then Return False Else 'Aqui deberian verificarse los permisos del usuario para ejecutar el 'servicio. If value.UserName = "user" And value.Password = "pwd" Then Return True Else Return False End If End If
End Function
End Class
Eso es todo por parte del WebService. Cuando alguien llame al método web "SecureWebMethod" éste verificará la existencia de la información del usuario en el sobre Soap y validará la misma. Si todo se encuentra en orden el método se ejecutará con éxito. Abajo detallamos un bosquejo de la petición Soap con el header de información del usuario, necesario para llamar al WebService: POST /SecureWebService/SecureWebService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length SOAPAction: "http://tempuri.org/SecureWebService/SecureWebService/SecureWebMethod"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthenticationHeader xmlns="http://tempuri.org/SecureWebService/SecureWebService">
<UserName>string</UserName> <Password>string</Password> </AuthenticationHeader>
</soap:Header>
<soap:Body>
<SecureWebMethod xmlns="http://tempuri.org/SecureWebService/SecureWebService" />
</soap:Body>
</soap:Envelope>
Ahora realizaremos una página Aspx que utilizaremos como cliente del webservice. Creamos una página aspx llamada Test.aspx en un proyecto web nuevo. Para poder hacer referencia al webservice antes creado agregamos una referencia web al mismo. En el código de la página colocamos el siguiente código en el botón que realiza "submit":
Private Sub btnExec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExec.Click Dim ServiceToCall As New SecureService.SecureWebService
'Creo un header soap con para portar las credenciales del usuario Dim Authentication As New SecureService.AuthenticationHeader
'Inicializo el header con la informacion del usuario Authentication.UserName = txtUser.Text Authentication.Password = txtPwd.Text
'Asigno las credenciales ServiceToCall.AuthenticationHeaderValue = Authentication
'Llamo al metodo txtResult.Text = ServiceToCall.SecureWebMethod() End Sub
En la siguiente imagen veremos que el webservice devuelve un mensaje de autenticación negativa debido a que no se provee un password correcto:
En la siguiente imagen proveemos datos correctos y el webservice valida los mismos satisfactoriamente:
TrackbacksThe trackback URL for this entry is: http://misopiniones.spaces.live.com/blog/cns!2737DC89A4AAB26B!212.trak Weblogs that reference this entry
|
|
|