Neste artigo, quero mostrar como criar um webservices seguro, ou seja, utilizando token, usuário, senha e soapHeader. Assim fica melhor do que colocar como parâmetro de entrada usuário e senha. Fica um pouco mais escondido do que o normal, porém não é tão seguro assim, caso os mesmos não estejam criptografados, utilizando SSL e outras coisas mais.
É lógico que ajuda colocar os dados no soapHeader, fica melhor do que vindo como parâmetro de entrada de um método porque não fica à vista. É importante dizer que não é só isso que faz um webservices ficar seguro.
Requisitos:
Ferramenta: Visual Studio.NET 2008 Team System
Framework: Versão 3.5
Tecnologia: WebService / SOA
Partes que não vou mostrar no artigo.
A camada responsável pelo acesso ao banco de dados. Lembrando que a melhor forma de utilizar o acesso a dados é usando MVC com interface e tudo de direito. Não fiz como MVC ainda, preciso primeiro mostrar a criação simples e depois complicar mais um pouco com camadas.
WebServices, para que serve?
Com o surgimento do software, sistemas e sites, surgiu também a necessidade de vincular dados entre eles, ou seja, comunicação entre sistemas de plataformas diferentes. Os dados precisam ser passados de um lado para outro de forma dinâmica e personalizada. Antigamente, os dados eram colocados em um arquivo .txt e mandados via e-mail, via upload e outros.
Havia um problema nesse envio de arquivo, porque não existia um padrão entre os desenvolvedores ou sistemas que os criavam. A leitura deles era problemática pois a coisa era posicional, ou seja, tinha que contar posição a posição para pegar os dados. Qualquer mudança da posição de dado prejudicava todo o sistema de leitura e gravação.
Respondendo à pergunta, o webservices serve para facilitar a comunicação entre sistemas de forma mais simples e padronizada.
Pode-se usar qualquer linguagem pode usar?
Qualquer linguagem que utilize ou tenha suporte de leitura de xml ou qualquer outra coisa com xml poder utilizar ou “consumir” um webservices. Linguagem orientada a objetos, estruturada, tudo acessa e tem capacidade de criar e consumir um serviço na web.
Qual a forma incorreta de usar WebServices?
No meu ponto de vista, um serviço web é tão quão importante como um sistema cliente / servidor ou web. Muitas empresas deixam de considerar isso e tratam como uma coisa qualquer, não pode ser assim.
Utilizar o serviço web com endereço http normalmente é um erro; deve ser feito utilizando https. Não usar criptografia nos dados importantes como: usuário, senha, token e outros é uma forma incorreta de utilizar serviço web.
Colocar parâmetro de entrada como “senha” é uma forma incorreta de utilizar o serviço web. A melhor forma é usar no soapHeader, por ficar mais escondido.
Retornar tipo de dado que apenas uma linguagem utiliza, por exemplo: object “DataSet”. Um objeto criado pela Microsoft e usado apenas pela mesma. Caso uma outra linguagem ou plataforma for consumir o serviço, o seu retorno será ilegível. Exemplo: Java J2EE, Payton, C++, C e outros.
Desenvolvimento do aplicativo
Depois de ter explicado um pouco sobre o que é, como funciona, como utilizar e não fazer, passo para a etapa de criar um serviço web e consumi-lo de forma mais simples e fácil. Utilizei o mesmo exemplo do artigo anterior chamado “Usando SoapHeader – segurança em webservice”. Criei outro método e acrescentei outro dado necessários no soapHeader.

Imagem 1.1
Na imagem 1.1 mostro que o projeto chamado SoapHeader possui um serviço web chamado WebService1.asmx, uma página Default.aspx e uma Web References chamada wssseguro.
Classe de autenticação
Criei uma classe de autenticação, responsável pela autenticação e verificação de usuário, senha e token no soapHeader. Veja o code 1.1.
public class AuthenticationSoapHeader : SoapHeader<br /> {<br /> private string _devToken;<br /> private string _user;<br /> private string _pw;<br /><br /> public string Pw<br /> {<br /> get { return _pw; }<br /> set { _pw = value; }<br /> }<br /><br /> public string User<br /> {<br /> get { return _user; }<br /> set { _user = value; }<br /> }<br /><br /> public string DevToken<br /> {<br /> get { return _devToken; }<br /> set { _devToken = value; }<br /> }<br /><br /> public AuthenticationSoapHeader() { }<br /><br /> public AuthenticationSoapHeader(string devToken, string user, string pw)<br /> {<br /> _devToken = devToken;<br /> _user = user;<br /> _pw = pw;<br /> }<br /> }Code 1.1
Explicação: A primeira coisa foi estender a classe de SoapHeader. (Code 1.2)
public class AuthenticationSoapHeader : SoapHeaderCode 1.2
A segunda tarefa feita foi declarar variáveis para gerar as propriedades, referentes ao mesmo dado, usuário, senha e token. Gerei dois métodos construtores na classe, uma que não tem parâmetro de entrada e outro que tem três parâmetros de entrada. Isso é necessário (Code 1.3).
public AuthenticationSoapHeader() { }<br /><br /> public AuthenticationSoapHeader(string devToken, string user, string pw)<br /> {<br /> _devToken = devToken;<br /> _user = user;<br /> _pw = pw;<br /> }Code 1.3
Explicação: Coloquei o construtor recebendo os três parâmetros e adicionando os mesmos as propriedades criadas para um melhor uso quem o chamar.
No artigo anterior, mostrei como verificar uma autenticação do usuário no banco de dados. Para explicar um pouco melhor, deixo o usuário digitar a senha, gero um hash dela com um número aleatório e a senha gerada. Depois, gravo no banco de dados com esse número de controle, como se fosse um id de controle para cada usuário. Para a autenticação do usuário, basta pegar esse id de controle, pegar a senha que usuário digitou e comparar os dados. Caso seja verdadeiro, o mesmo logou sem qualquer problema.
Peguei esse artigo e gerei um serviço na web de autenticação e verificação de usuário. Os próximos passos são: gerar o método que cria um número aleatório para cada usuário e, em seguida, gerar um método que calcula hash.
/// <summary><br /> /// Método que gerar numero aleatorio<br /> /// </summary><br /> /// <returns>int</returns><br /> private int GerarNrAleatorio()<br /> {<br /> Random rnd = new Random();<br /> return rnd.Next();<br /> }Code 1.4
Gerar um número aleatório com o Random().
/// <summary><br /> /// Método que calcula hash dinâmica<br /> /// </summary><br /> /// <param name="input">por exemplo: password</param><br /> /// <returns>string</returns><br /> private string CalcularHash(string input)<br /> {<br /> MD5 md5 = System.Security.Cryptography.MD5.Create();<br /> byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);<br /> byte[] hash = md5.ComputeHash(inputBytes);<br /><br /> StringBuilder str = new StringBuilder();<br /> for (int i = 0; i < hash.Length; i++)<br /> {<br /> str.Append(hash[i].ToString("X2"));<br /> }<br /> return str.ToString();<br /> }Code 1.5
Explicação: Utilizei a classe Cryptography para gerar em Bytes a esse hash. Depois disso utilizei também o md5, fiz um for para gerar letra por letra.
O passo seguinte é gerar o um método público chamado AutenticarUsuario() sem qualquer parâmetro de entrada, porém dentro do mesmo é verificado todo o soapHeader.
public object AutenticarUsuario()<br /> {<br /> if (ValidationSoap != null &&<br /> ValidationSoap.User != null &&<br /> ValidationSoap.Pw != null &&<br /> ValidationSoap.DevToken != null)<br /> {<br /> //abro o banco de dados<br /> conn = DTecDefination.GetHelper();<br /><br /> //toda regra para buscar o usuario e autenticar<br /> string numero;<br /> StringBuilder str = new StringBuilder();<br /> str.Append("select controle from tb_usuario where nome=@nome");<br /><br /> try<br /> {<br /> SqlCommand cmd = new SqlCommand(str.ToString());<br /> cmd.Parameters.Add("@nome", SqlDbType.VarChar).Value = ValidationSoap.User;<br /><br /> conn.GetSourceConnection();<br /> DataSet dtSet = conn.ExecutaDataSetParameter(cmd);<br /><br /> if (dtSet != null)<br /> if (dtSet.Tables[0].Rows.Count > 0)<br /> {<br /> numero = dtSet.Tables[0].Rows[0]["controle"].ToString();<br /> string hash = CalcularHash(numero + ValidationSoap.Pw);<br /><br /> StringBuilder strHash = new StringBuilder();<br /> strHash.Append("select chave from tb_usuario where senha = @hashT");<br /><br /> SqlCommand bdCommand = new SqlCommand(strHash.ToString());<br /> bdCommand.Parameters.Add("@hashT", SqlDbType.VarChar).Value = hash;<br /><br /> object obj = conn.ExecutaScalarParameter(bdCommand);<br /><br /> if (obj != null)<br /> return obj;<br /> else<br /> return null;<br /> }<br /> else<br /> return null;<br /> else<br /> return null;<br /> }<br /> catch (Exception ex)<br /> {<br /> return null;<br /> }<br /> }<br /> else<br /> return null;<br /> }Code 1.6
Explicação: A primeira coisa foi verificar se o ValidationSoap é diferente de null, em seguida verifiquei o User, Pw e DevToken. Abri o banco de dados, gerei o select no banco de dados, lembro que pode ser usado stored procedure sem qualquer problema. Depois executei o comando ExecutaDataSetParameter.
Verifiquei se trouxe algum dado no DataSet, calculei o Hash passando o número e a senha do usuário, caso seja igual ao método, retorna um Object com o número do usuário. Caso queira gerar uma sessão para identificar o usuário e tudo mais. Compilei o código e ficou tudo ok. Preciso adicionar o webservice junto ao projeto (Imagem 1.2).

Imagem 1.2
Cliquei com o botão direito em cima de Web References e escolhi a opção Add Web Referece. Adicionei o endereço do localhost e dei um nome a ele. Lembro que o endereço é particular de cada um, isso porque cada projeto pode colocar uma porta diferente no momento. O endereço gerado pelo meu servidor de aplicação do Visual Studio .NET Team System (http://localhost:1189/webservice1.asmx). O nome adicionado foi wsseguro.
Consumir WebService
De agora em diante, preciso consumir o webservice gerado na aplicação. Lembro que existe uma página default.aspx.cs no projeto (Code 1.7).
protected void Page_Load(object sender, EventArgs e)<br /> {<br /> wsseguro.WebService1 ws = new SoapTeste.wsseguro.WebService1();<br /> wsseguro.AuthenticationSoapHeader soap = new SoapTeste.wsseguro.AuthenticationSoapHeader();<br /> soap.DevToken = "123425";<br /> soap.User = "mauricio";<br /> soap.Pw = "mauricio";<br /> ws.AuthenticationSoapHeaderValue = soap;<br /><br /> Object obj = ws.AutenticarUsuario();<br /> if (obj == null)<br /> {<br /> Response.Write("Usuário não autorizado");<br /> }<br /> else<br /> {<br /> int numero = int.Parse(obj.ToString());<br /> Response.Write("Usuario autorizado -" + numero);<br /> }<br /> }Code 1.7
Primeiro, criei uma instância do webservice, depois o soap. Adicionei os valores no soap e falei para o webservice gerado pela variável ws, o seu valor. O passo seguinte foi chamar o método AutenticarUsuario(). Depois, precisei apenas verificar os dados para mostrar a mensagem na tela (Imagem 1.3).

Imagem 1.3
Funcionou perfeitamente a autenticação e autorização do usuário logado. Daí em diante, a sua criatividade pode ser exercitada livremente. Caso coloque um usuário ou senha inválidos, ou mesmo o token, veja a mensagem que é apresentada na tela (Imagem 1.4).

Imagem 1.4
Bom, eu fico por aqui. Qualquer dúvida favor entrar em contato.








