Tuesday, October 13, 2009

WebServices Autenticação SOAP Header

Sempre que estamos a falar de webservices surge uma questão.

E a segurança?

Como vou autenticar os utilizadores?

Uma das formas de fazer isso é com Soap Headers.


Vamos por passos.

1º Crie a seguinte classe( com o nome que quiser )



using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Web.Services.Protocols;

using System.Security.Cryptography;



///
<summary>

/// Summary description for AuthHeader

///
</summary>

public
class
AuthHeader:SoapHeader

{

   

        public
string Username;


public
string Password;




public
string decrypt(string data)

{

System.IO.MemoryStream msDecrypt = null;


CryptoStream csDecrypt = null;

System.IO.StreamReader srDecrypt = null;



System.Security.Cryptography.RijndaelManaged aesAlg = null;




string plaintext = null;


try

{


// Create a RijndaelManaged object


// with the specified key (IV parameter is obmitted because of ECB CipherMode).

aesAlg = new System.Security.Cryptography.RijndaelManaged();

aesAlg.Key = System.Text.Encoding.UTF8.GetBytes("01030123012390129012901A");

aesAlg.Mode = CipherMode.ECB;


// set PaddingMode.Zeros in order to use the same padding mode as in flash actionscript class

aesAlg.Padding = PaddingMode.Zeros;




// Create a decrytor to perform the stream transform.


ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);




// Create the streams used for decryption.

msDecrypt = new System.IO.MemoryStream(Convert.FromBase64String(data));

csDecrypt = new
CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);

srDecrypt = new System.IO.StreamReader(csDecrypt);




// Read the decrypted bytes from the decrypting stream


// and place them in a string.

plaintext = srDecrypt.ReadToEnd();


return plaintext.Replace("\0", "");

}


finally

{


// Clean things up.


// Close the streams.


if (srDecrypt != null)

srDecrypt.Close();


if (csDecrypt != null)

csDecrypt.Close();


if (msDecrypt != null)

msDecrypt.Close();




// Clear the RijndaelManaged object.


if (aesAlg != null)

aesAlg.Clear();

}



}











}



2º No seu webservice adicione as seguintes linhas

public
class
SeuWebsercice : System.Web.Services.WebService

{


public
AuthHeader Authentication;

….

E em cada método
adicionar

[SoapHeader("Authentication", Required = true)]

Exemplo:

[SoapHeader("Authentication", Required = true)]

[WebMethod]


public
bool xptoMethod()

{





//validateUser é apenas exemplo.. podera ser um login
if(!System.Web.Security.Membership.ValidateUser(Authentication.decrypt(Authentication.Username),

Authentication.decrypt(Authentication.Password)))



{


return
false;

}



NOTA: neste exemplo é necessário efectuar a validação em cada metodo, no entando o melhor (dependendo do que se pretende) será guardar em sessão se o user ta autenticado



No lado do cliente:

Criar a classe de encriptação


private
static
string Encrypt(string input)

{



System.Security.Cryptography.RijndaelManaged aesAlg = null;




// Create a RijndaelManaged object


// with the specified key (IV parameter is obmitted because of ECB CipherMode).

aesAlg = new System.Security.Cryptography.RijndaelManaged();



//IMPORTANTE: esta chave ter que ser a mesma

aesAlg.Key = System.Text.Encoding.UTF8.GetBytes("01030123012390129012901A");

aesAlg.Mode = CipherMode.ECB;


// set PaddingMode.Zeros in order to use the same padding mode as in flash actionscript class

aesAlg.Padding = PaddingMode.Zeros;




// Create a decrytor to perform the stream transform.


ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);


byte[] toEncrypt = System.Text.Encoding.UTF8.GetBytes(input);

System.IO.MemoryStream msEncrypt = new System.IO.MemoryStream();


CryptoStream csEncrypt = new
CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);




// toEncrypt = textConverter.GetBytes(input);



csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);

csEncrypt.FlushFinalBlock();




// return msEncrypt.ToArray();


return
Convert.ToBase64String(msEncrypt.ToArray());

}



Na classe onde ira ser chamado o webservice:

static WebSync.Sync websync = new WebSync.Sync();


static WebSync.AuthHeader aut = new WebSync.AuthHeader();

aut.Username = Encrypt(config.AppSettings.Settings["username"].Value);
aut.Password = Encrypt(config.AppSettings.Settings["password"].Value);

websync.AuthHeaderValue = aut;



O resto ( a chamada ao metodo) não é preciso alterar nada..
ex: webSync.xpto();

No comments:

Post a Comment