Gustavo's profileGustavo BonanseaBlogLists Tools Help
    July 06

    Seguridad: Autenticación de usuarios en un Web Service

    El 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:

    GB

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    The trackback URL for this entry is:
    http://misopiniones.spaces.live.com/blog/cns!2737DC89A4AAB26B!212.trak
    Weblogs that reference this entry
    • None