Query strings are very easy way of passing data from one page to another page. The problem with query strings is that the information is visible in the url. However, many developers have been using this way carelessly including me and we are vulnerable to use the query string in some circumstances. In my experience, one friend of mine web site had attacked by hacker using SQL Injection method since he used the Inline SQL Statemnet and Query String in his programming. Hence query strings are able to see, we should encrypt the parameters where it is confidential or not so that we prevent our application from malicious access. In the following sample, I show you using RC2 encryption for the query strings when you click "Details" link on Gridview and it go to other page with encrypted query strings.
Create BasePage.cs as below.
using System;
using System.Collections.Generic;
using System.Web;
using System.Text;
using System.IO;
using System.Collections.Specialized;
using System.Security.Cryptography;
public class BasePage : System.Web.UI.Page
{
// Key management for scrambling support
public byte[] ScrambleKey
{
set
{
byte[] key = value;
if (null == key)
{
// Use existing key if non provided
key = ScrambleKey;
}
Session["ScrambleKey"] = key;
}
get
{
byte[] key = (byte[])Session["ScrambleKey"];
if (null == key)
{
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.GenerateKey();
key = rc2.Key;
Session["ScrambleKey"] = key;
}
return key;
}
}
// Initialization vector management for scrambling support
public byte[] ScrambleIV
{
set
{
byte[] key = value;
if (null == key)
{
key = ScrambleIV;
}
Session["ScrambleIV"] = key;
}
get
{
byte[] key = (byte[])Session["ScrambleIV"];
if (null == key)
{
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.GenerateIV();
key = rc2.IV;
Session["ScrambleIV"] = key;
}
return key;
}
}
public string Encrypt(string message)
{
UTF8Encoding textConverter = new UTF8Encoding();
RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider();
//Convert the data to a byte array.
byte[] toEncrypt = textConverter.GetBytes(message);
//Get an encryptor.
ICryptoTransform encryptor = rc2CSP.CreateEncryptor(ScrambleKey, ScrambleIV);
//Encrypt the data.
MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
//Write all data to the crypto stream and flush it.
// Encode length as first 4 bytes
byte[] length = new byte[4];
length[0] = (byte)(message.Length & 0xFF);
length[1] = (byte)((message.Length >> 8) & 0xFF);
length[2] = (byte)((message.Length >> 16) & 0xFF);
length[3] = (byte)((message.Length >> 24) & 0xFF);
csEncrypt.Write(length, 0, 4);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
//Get encrypted array of bytes.
byte[] encrypted = msEncrypt.ToArray();
// Convert to Base64 string
string b64 = Convert.ToBase64String(encrypted);
// Protect against URLEncode/Decode problem
string b64mod = b64.Replace('+', '@');
// Return a URL encoded string
return HttpUtility.UrlEncode(b64mod);
}
public string Decrypt(string scrambledMessage)
{
UTF8Encoding textConverter = new UTF8Encoding();
RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider();
// URL decode , replace and convert from Base64
string b64mod = HttpUtility.UrlDecode(scrambledMessage);
// Replace '@' back to '+' (avoid URLDecode problem)
string b64 = b64mod.Replace('@', '+');
// Base64 decode
byte[] encrypted = Convert.FromBase64String(b64);
//Get a decryptor that uses the same key and IV as the encryptor.
ICryptoTransform decryptor = rc2CSP.CreateDecryptor(ScrambleKey, ScrambleIV);
//Now decrypt the previously encrypted message using the decryptor
// obtained in the above step.
MemoryStream msDecrypt = new MemoryStream(encrypted);
CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
byte[] fromEncrypt = new byte[encrypted.Length - 4];
//Read the data out of the crypto stream.
byte[] length = new byte[4];
csDecrypt.Read(length, 0, 4);
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
int len = (int)length[0] | (length[1] << 8) | (length[2] << 16) | (length[3] << 24);
//Convert the byte array back into a string.
return textConverter.GetString(fromEncrypt).Substring(0, len);
}
public NameValueCollection DecryptQueryString(string scrambledMessage)
{
// Decode the query string
string queryString = Decrypt(scrambledMessage);
NameValueCollection result = new NameValueCollection();
char[] splitChar = new char[] { '&' };
char[] equalChar = new char[] { '=' };
// Split query string to components
foreach (string s in queryString.Split(splitChar))
{
// split each component to key and value
string[] keyVal = s.Split(equalChar, 2);
string key = keyVal[0];
string val = String.Empty;
if (keyVal.Length > 1) val = keyVal[1];
// Add to the hashtable
result.Add(key, val);
}
// return the resulting hashtable
return result;
}
}
Create a .aspx page and extend BasePage.cs we created before.
Put the following gridview that use ObjectDataSource and "Northwind" DB in <form> tag(for creating the below gridview and data access, you can see in the my previous post).
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" CellPadding="4"
AllowPaging="True" AllowSorting="True" AlternatingRowStyle-Wrap="True"
DataSourceID="ObjectDataSource2" EmptyDataText="There is no data.">
<RowStyle BackColor="#EFF3FB" />
<Columns>
<asp:BoundField HeaderText="No." DataField="No" />
<asp:BoundField HeaderText="CustomerID" DataField="CustomerID" SortExpression="CustomerID"/>
<asp:BoundField HeaderText="CompanyName" DataField="CompanyName" SortExpression="CompanyName" />
<asp:BoundField HeaderText="ContactName" DataField="ContactName" SortExpression="ContactName" />
<asp:TemplateField HeaderText="Action" >
<ItemTemplate>
<asp:HyperLink ID="hlkdetail" runat="server"
NavigateUrl='<%# querystringencodedecode.aspx?query=" + Encrypt("ID=" + Eval("CustomerID"))%>'
Text="Detail"></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server" SelectMethod="GridDataPage"
TypeName="DAL" SelectCountMethod="DataRowCount"
SortParameterName="SortExpression" EnablePaging="True">
<SelectParameters>
<asp:Parameter Name="maximumRows" Type="Int32" />
<asp:Parameter Name="startRowIndex" Type="Int32" />
<asp:Parameter Name="SortExpression" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
Create querystringencodedecode.aspx and put the below label control to <form> tag.
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
Add the following code to Page_Load.
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["query"]))
{
System.Collections.Specialized.NameValueCollection querystring = DecryptQueryString(Request.QueryString["query"]);
string id = querystring["ID"];
//Handle id here.
Label1.Text = id.ToString();
}
}
Here are two snapshots to show how this example works.
Original post : http://www.codeproject.com/kb/aspnet/ScrambleQueryStrings.aspx?fid=220116&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&display=Mobile&prof=False
Create BasePage.cs as below.
using System;
using System.Collections.Generic;
using System.Web;
using System.Text;
using System.IO;
using System.Collections.Specialized;
using System.Security.Cryptography;
public class BasePage : System.Web.UI.Page
{
// Key management for scrambling support
public byte[] ScrambleKey
{
set
{
byte[] key = value;
if (null == key)
{
// Use existing key if non provided
key = ScrambleKey;
}
Session["ScrambleKey"] = key;
}
get
{
byte[] key = (byte[])Session["ScrambleKey"];
if (null == key)
{
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.GenerateKey();
key = rc2.Key;
Session["ScrambleKey"] = key;
}
return key;
}
}
// Initialization vector management for scrambling support
public byte[] ScrambleIV
{
set
{
byte[] key = value;
if (null == key)
{
key = ScrambleIV;
}
Session["ScrambleIV"] = key;
}
get
{
byte[] key = (byte[])Session["ScrambleIV"];
if (null == key)
{
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.GenerateIV();
key = rc2.IV;
Session["ScrambleIV"] = key;
}
return key;
}
}
public string Encrypt(string message)
{
UTF8Encoding textConverter = new UTF8Encoding();
RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider();
//Convert the data to a byte array.
byte[] toEncrypt = textConverter.GetBytes(message);
//Get an encryptor.
ICryptoTransform encryptor = rc2CSP.CreateEncryptor(ScrambleKey, ScrambleIV);
//Encrypt the data.
MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
//Write all data to the crypto stream and flush it.
// Encode length as first 4 bytes
byte[] length = new byte[4];
length[0] = (byte)(message.Length & 0xFF);
length[1] = (byte)((message.Length >> 8) & 0xFF);
length[2] = (byte)((message.Length >> 16) & 0xFF);
length[3] = (byte)((message.Length >> 24) & 0xFF);
csEncrypt.Write(length, 0, 4);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
//Get encrypted array of bytes.
byte[] encrypted = msEncrypt.ToArray();
// Convert to Base64 string
string b64 = Convert.ToBase64String(encrypted);
// Protect against URLEncode/Decode problem
string b64mod = b64.Replace('+', '@');
// Return a URL encoded string
return HttpUtility.UrlEncode(b64mod);
}
public string Decrypt(string scrambledMessage)
{
UTF8Encoding textConverter = new UTF8Encoding();
RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider();
// URL decode , replace and convert from Base64
string b64mod = HttpUtility.UrlDecode(scrambledMessage);
// Replace '@' back to '+' (avoid URLDecode problem)
string b64 = b64mod.Replace('@', '+');
// Base64 decode
byte[] encrypted = Convert.FromBase64String(b64);
//Get a decryptor that uses the same key and IV as the encryptor.
ICryptoTransform decryptor = rc2CSP.CreateDecryptor(ScrambleKey, ScrambleIV);
//Now decrypt the previously encrypted message using the decryptor
// obtained in the above step.
MemoryStream msDecrypt = new MemoryStream(encrypted);
CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
byte[] fromEncrypt = new byte[encrypted.Length - 4];
//Read the data out of the crypto stream.
byte[] length = new byte[4];
csDecrypt.Read(length, 0, 4);
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
int len = (int)length[0] | (length[1] << 8) | (length[2] << 16) | (length[3] << 24);
//Convert the byte array back into a string.
return textConverter.GetString(fromEncrypt).Substring(0, len);
}
public NameValueCollection DecryptQueryString(string scrambledMessage)
{
// Decode the query string
string queryString = Decrypt(scrambledMessage);
NameValueCollection result = new NameValueCollection();
char[] splitChar = new char[] { '&' };
char[] equalChar = new char[] { '=' };
// Split query string to components
foreach (string s in queryString.Split(splitChar))
{
// split each component to key and value
string[] keyVal = s.Split(equalChar, 2);
string key = keyVal[0];
string val = String.Empty;
if (keyVal.Length > 1) val = keyVal[1];
// Add to the hashtable
result.Add(key, val);
}
// return the resulting hashtable
return result;
}
}
Create a .aspx page and extend BasePage.cs we created before.
Put the following gridview that use ObjectDataSource and "Northwind" DB in <form> tag(for creating the below gridview and data access, you can see in the my previous post).
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" CellPadding="4"
AllowPaging="True" AllowSorting="True" AlternatingRowStyle-Wrap="True"
DataSourceID="ObjectDataSource2" EmptyDataText="There is no data.">
<RowStyle BackColor="#EFF3FB" />
<Columns>
<asp:BoundField HeaderText="No." DataField="No" />
<asp:BoundField HeaderText="CustomerID" DataField="CustomerID" SortExpression="CustomerID"/>
<asp:BoundField HeaderText="CompanyName" DataField="CompanyName" SortExpression="CompanyName" />
<asp:BoundField HeaderText="ContactName" DataField="ContactName" SortExpression="ContactName" />
<asp:TemplateField HeaderText="Action" >
<ItemTemplate>
<asp:HyperLink ID="hlkdetail" runat="server"
NavigateUrl='<%# querystringencodedecode.aspx?query=" + Encrypt("ID=" + Eval("CustomerID"))%>'
Text="Detail"></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server" SelectMethod="GridDataPage"
TypeName="DAL" SelectCountMethod="DataRowCount"
SortParameterName="SortExpression" EnablePaging="True">
<SelectParameters>
<asp:Parameter Name="maximumRows" Type="Int32" />
<asp:Parameter Name="startRowIndex" Type="Int32" />
<asp:Parameter Name="SortExpression" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
Create querystringencodedecode.aspx and put the below label control to <form> tag.
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
Add the following code to Page_Load.
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["query"]))
{
System.Collections.Specialized.NameValueCollection querystring = DecryptQueryString(Request.QueryString["query"]);
string id = querystring["ID"];
//Handle id here.
Label1.Text = id.ToString();
}
}
Here are two snapshots to show how this example works.
![]() | |
Gridview page |
When you click on Detail link, it go to below page with encrypted query string and then decrypt the query string again and show the parameter value on page.
![]() | |
querystringencodeDecode.aspx |
You should avoid the query string method for passing data between pages when your data is important.
Original post : http://www.codeproject.com/kb/aspnet/ScrambleQueryStrings.aspx?fid=220116&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&display=Mobile&prof=False
No comments:
Post a Comment