Utilização correta e segura de QueryString
Boa noite,
Estou implementando querystring em minha aplicação principalmente no logon do usuário. Gostaria de saber como poderia criptografar a querystring para que um possivel invasor não utilize desses dados para entrar em minha aplicação. Qual forma também poderia utilizar para que a chave gerada seja aleatória e tenha um tempo de vida ( principalmente tratando-se de logon de usuários )
Abraços
Vinicius
Vinicius Cezar
Curtidas 0
Respostas
Fabio Mans
15/06/2009
Olá Vinícios, muito boa sua dúvida, poucos programadores se preocupam com este assunto.
Nos meu programas eu utilizo a classe abaixo.
StringHelpers.cs
using System;
using System.Web;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Collections.Specialized;
public class StringHelpers
{
#region Constants
private const char QUERY_STRING_DELIMITER = '&';
#endregion Constants
#region Members
private static RijndaelManaged _cryptoProvider;
//128 bit encyption: DO NOT CHANGE
private static readonly byte[] Key = { 18, 19, 8, 24, 36, 22, 4, 22, 17, 5, 11, 9, 13, 15, 06, 23 };
private static readonly byte[] IV = { 14, 2, 16, 7, 5, 9, 17, 8, 4, 47, 16, 12, 1, 32, 25, 18 };
#endregion Members
#region Constructor
static StringHelpers()
{
_cryptoProvider = new RijndaelManaged();
_cryptoProvider.Mode = CipherMode.CBC;
_cryptoProvider.Padding = PaddingMode.PKCS7;
}
#endregion Constructor
#region Methods
/// <summary>
/// Encrypts a given string.
/// </summary>
/// <param name="unencryptedString">Unencrypted string</param>
/// <returns>Returns an encrypted string</returns>
public static string Encrypt(string unencryptedString)
{
byte[] bytIn = ASCIIEncoding.ASCII.GetBytes(unencryptedString);
// Create a MemoryStream
MemoryStream ms = new MemoryStream();
// Create Crypto Stream that encrypts a stream
CryptoStream cs = new CryptoStream(ms,
_cryptoProvider.CreateEncryptor(Key, IV),
CryptoStreamMode.Write);
// Write content into MemoryStream
cs.Write(bytIn, 0, bytIn.Length);
cs.FlushFinalBlock();
byte[] bytOut = ms.ToArray();
return Convert.ToBase64String(bytOut);
}
/// <summary>
/// Decrypts a given string.
/// </summary>
/// <param name="encryptedString">Encrypted string</param>
/// <returns>Returns a decrypted string</returns>
public static string Decrypt(string encryptedString)
{
if (encryptedString.Trim().Length != 0)
{
// Convert from Base64 to binary
byte[] bytIn = Convert.FromBase64String(encryptedString);
// Create a MemoryStream
MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length);
// Create a CryptoStream that decrypts the data
CryptoStream cs = new CryptoStream(ms,
_cryptoProvider.CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
// Read the Crypto Stream
StreamReader sr = new StreamReader(cs);
return sr.ReadToEnd();
}
else
{
return "";
}
}
public static NameValueCollection DecryptQueryString(string queryString)
{
if (queryString.Length != 0)
{
//Decode the string
string decodedQueryString = HttpUtility.UrlDecode(queryString);
//Decrypt the string
string decryptedQueryString = Decrypt(decodedQueryString);
//Now split the string based on each parameter
string[] actionQueryString = decryptedQueryString.Split(new char[] { QUERY_STRING_DELIMITER });
NameValueCollection newQueryString = new NameValueCollection();
//loop around for each name value pair.
for (int index = 0; index < actionQueryString.Length; index++)
{
string[] queryStringItem = actionQueryString[index].Split(new char[] { '=' });
newQueryString.Add(queryStringItem[0], queryStringItem[1]);
}
return newQueryString;
}
else
{
//No query string was passed in.
return null;
}
}
public static string EncryptQueryString(NameValueCollection queryString)
{
//create a string for each value in the query string passed in.
string tempQueryString = "";
for (int index = 0; index < queryString.Count; index++)
{
tempQueryString += queryString.GetKey(index) + "=" + queryString[index];
if (index != queryString.Count - 1)
{
tempQueryString += QUERY_STRING_DELIMITER;
}
}
return EncryptQueryString(tempQueryString);
}
/// <summary>
/// You must pass in a string that uses the QueryStringHelper.DELIMITER as the delimiter.
/// This will also append the "?" to the beginning of the query string.
/// </summary>
/// <param name="queryString"></param>
/// <returns></returns>
public static string EncryptQueryString(string queryString)
{
return string.Format("?", HttpUtility.UrlEncode(Encrypt(queryString)));
}
#endregion Methods
}
Em outra classe chamada BasePage eu crie os seguintes métodos
using System;
using System.Collections.Specialized;
using System.IO;
using System.Web.UI;
using System.Web.UI.HtmlControls;
public class BasePage : Page
{
protected override void OnLoad(EventArgs e)
{
// add onfocus and onblur javascripts to all input controls on the forum,
// so that the active control has a difference appearance
Helpers.SetInputControlsHighlight(this, "highlight");
// Set the page's title, if necessary
if (string.IsNullOrEmpty(Page.Title) || Page.Title == "Untitled Page")
{
// Determine the filename for this page
string fileName = Path.GetFileNameWithoutExtension(Request.PhysicalPath);
Page.Title = "GRUPO SBF - R&S Solicitação de Contratação - (" + fileName + ")";
}
HtmlMeta metaDescription = new HtmlMeta();
metaDescription.Name = "description";
metaDescription.Content = "SELAÇÃO";
//Define uma tag metadata
//Adicionando
Page.Header.Controls.Add(metaDescription);
base.OnLoad(e);
}
public static NameValueCollection DecryptQueryString(string queryString)
{
return StringHelpers.DecryptQueryString(queryString);
}
public static string EncryptQueryString(NameValueCollection queryString)
{
return StringHelpers.EncryptQueryString(queryString);
}
public static string EncryptQueryString(string queryString)
{
return StringHelpers.EncryptQueryString(queryString);
}
}
Enfim para criptografar eu faço o seguinte
string solicitacao = EncryptQueryString("solicitacao=" + 1089);
Para recuperar
NameValueCollection queryString = DecryptQueryString(Request.QueryString.ToString());
if (queryString != null)
{
int idSolicitacao = Convert.ToInt32(queryString["solicitacao"]); //Resultado 1089
}
Resumindo crie duas classes conforme o exemplo abaixo
Na página você deve herdar a BasePage
public partial class ConsultaSolicitacao : BasePage (Minha página herdando de basepage
Espero ter ajudado.
Fabio
Nos meu programas eu utilizo a classe abaixo.
StringHelpers.cs
using System;
using System.Web;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Collections.Specialized;
public class StringHelpers
{
#region Constants
private const char QUERY_STRING_DELIMITER = '&';
#endregion Constants
#region Members
private static RijndaelManaged _cryptoProvider;
//128 bit encyption: DO NOT CHANGE
private static readonly byte[] Key = { 18, 19, 8, 24, 36, 22, 4, 22, 17, 5, 11, 9, 13, 15, 06, 23 };
private static readonly byte[] IV = { 14, 2, 16, 7, 5, 9, 17, 8, 4, 47, 16, 12, 1, 32, 25, 18 };
#endregion Members
#region Constructor
static StringHelpers()
{
_cryptoProvider = new RijndaelManaged();
_cryptoProvider.Mode = CipherMode.CBC;
_cryptoProvider.Padding = PaddingMode.PKCS7;
}
#endregion Constructor
#region Methods
/// <summary>
/// Encrypts a given string.
/// </summary>
/// <param name="unencryptedString">Unencrypted string</param>
/// <returns>Returns an encrypted string</returns>
public static string Encrypt(string unencryptedString)
{
byte[] bytIn = ASCIIEncoding.ASCII.GetBytes(unencryptedString);
// Create a MemoryStream
MemoryStream ms = new MemoryStream();
// Create Crypto Stream that encrypts a stream
CryptoStream cs = new CryptoStream(ms,
_cryptoProvider.CreateEncryptor(Key, IV),
CryptoStreamMode.Write);
// Write content into MemoryStream
cs.Write(bytIn, 0, bytIn.Length);
cs.FlushFinalBlock();
byte[] bytOut = ms.ToArray();
return Convert.ToBase64String(bytOut);
}
/// <summary>
/// Decrypts a given string.
/// </summary>
/// <param name="encryptedString">Encrypted string</param>
/// <returns>Returns a decrypted string</returns>
public static string Decrypt(string encryptedString)
{
if (encryptedString.Trim().Length != 0)
{
// Convert from Base64 to binary
byte[] bytIn = Convert.FromBase64String(encryptedString);
// Create a MemoryStream
MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length);
// Create a CryptoStream that decrypts the data
CryptoStream cs = new CryptoStream(ms,
_cryptoProvider.CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
// Read the Crypto Stream
StreamReader sr = new StreamReader(cs);
return sr.ReadToEnd();
}
else
{
return "";
}
}
public static NameValueCollection DecryptQueryString(string queryString)
{
if (queryString.Length != 0)
{
//Decode the string
string decodedQueryString = HttpUtility.UrlDecode(queryString);
//Decrypt the string
string decryptedQueryString = Decrypt(decodedQueryString);
//Now split the string based on each parameter
string[] actionQueryString = decryptedQueryString.Split(new char[] { QUERY_STRING_DELIMITER });
NameValueCollection newQueryString = new NameValueCollection();
//loop around for each name value pair.
for (int index = 0; index < actionQueryString.Length; index++)
{
string[] queryStringItem = actionQueryString[index].Split(new char[] { '=' });
newQueryString.Add(queryStringItem[0], queryStringItem[1]);
}
return newQueryString;
}
else
{
//No query string was passed in.
return null;
}
}
public static string EncryptQueryString(NameValueCollection queryString)
{
//create a string for each value in the query string passed in.
string tempQueryString = "";
for (int index = 0; index < queryString.Count; index++)
{
tempQueryString += queryString.GetKey(index) + "=" + queryString[index];
if (index != queryString.Count - 1)
{
tempQueryString += QUERY_STRING_DELIMITER;
}
}
return EncryptQueryString(tempQueryString);
}
/// <summary>
/// You must pass in a string that uses the QueryStringHelper.DELIMITER as the delimiter.
/// This will also append the "?" to the beginning of the query string.
/// </summary>
/// <param name="queryString"></param>
/// <returns></returns>
public static string EncryptQueryString(string queryString)
{
return string.Format("?", HttpUtility.UrlEncode(Encrypt(queryString)));
}
#endregion Methods
}
Em outra classe chamada BasePage eu crie os seguintes métodos
using System;
using System.Collections.Specialized;
using System.IO;
using System.Web.UI;
using System.Web.UI.HtmlControls;
public class BasePage : Page
{
protected override void OnLoad(EventArgs e)
{
// add onfocus and onblur javascripts to all input controls on the forum,
// so that the active control has a difference appearance
Helpers.SetInputControlsHighlight(this, "highlight");
// Set the page's title, if necessary
if (string.IsNullOrEmpty(Page.Title) || Page.Title == "Untitled Page")
{
// Determine the filename for this page
string fileName = Path.GetFileNameWithoutExtension(Request.PhysicalPath);
Page.Title = "GRUPO SBF - R&S Solicitação de Contratação - (" + fileName + ")";
}
HtmlMeta metaDescription = new HtmlMeta();
metaDescription.Name = "description";
metaDescription.Content = "SELAÇÃO";
//Define uma tag metadata
//Adicionando
Page.Header.Controls.Add(metaDescription);
base.OnLoad(e);
}
public static NameValueCollection DecryptQueryString(string queryString)
{
return StringHelpers.DecryptQueryString(queryString);
}
public static string EncryptQueryString(NameValueCollection queryString)
{
return StringHelpers.EncryptQueryString(queryString);
}
public static string EncryptQueryString(string queryString)
{
return StringHelpers.EncryptQueryString(queryString);
}
}
Enfim para criptografar eu faço o seguinte
string solicitacao = EncryptQueryString("solicitacao=" + 1089);
Para recuperar
NameValueCollection queryString = DecryptQueryString(Request.QueryString.ToString());
if (queryString != null)
{
int idSolicitacao = Convert.ToInt32(queryString["solicitacao"]); //Resultado 1089
}
Resumindo crie duas classes conforme o exemplo abaixo
Na página você deve herdar a BasePage
public partial class ConsultaSolicitacao : BasePage (Minha página herdando de basepage
Espero ter ajudado.
Fabio
GOSTEI 0
Vinicius Cezar
15/06/2009
Caro Mans,
Obrigado pelo seu post. Desde segunda-feira estava com problemas aqui para responder ou qualquer outra ação, mas parece que melhorou. Como programo em VB.NET, vou converter e testar nesse final de semana e te passo um feed-back.
Forte abraço!
Vinicius
GOSTEI 0
Fabio Mans
15/06/2009
Olá, você pode colocar uma classe C# em um projeto VB na pasta App_Code, não tem problema.
Fabio
Fabio
GOSTEI 0
Devmedia
15/06/2009
Vinicius,
a resposta do consultor solucionou a sua dúvida? Podemos encerrar o chamado?
a resposta do consultor solucionou a sua dúvida? Podemos encerrar o chamado?
GOSTEI 0
Devmedia
15/06/2009
Vinicius,
por falta de retorno estamos encerrando o chamado. Caso ainda tenha dúvidas sobre o assunto aqui abordado, por favor, poste neste mesmo chamado que o consultor voltará a lhe atender.
por falta de retorno estamos encerrando o chamado. Caso ainda tenha dúvidas sobre o assunto aqui abordado, por favor, poste neste mesmo chamado que o consultor voltará a lhe atender.
GOSTEI 0
Vinicius Cezar
15/06/2009
Obrigado Fabio pelo atendimento. Estive de férias e voltei agora. Vou implementar mas creio que já está 100%. qualquer dúvida te procuro. Obrigado.
GOSTEI 0