加密ASP.NET MVC中的URL中的ID
我试图在URL中对加密的ID进行编码。像这样:http://www.calemadr.com/Membership/Welcome/9xCnCLIwzxzBuPEjqJFxC6XJdAZqQsIDqNrRUJoW6229IIeeL4eXl5n1cnYapg+N加密ASP.NET MVC中的URL中的ID
但是,它要么不正确编码和我在加密斜杠“/”或我接收和错误从IIS:请求筛选模块被配置为拒绝包含请求一个双转义序列。
我试过不同的编码,每一个失败:
- HttpUtility.HtmlEncode
- HttpUtility.UrlEncode
- HttpUtility.UrlPathEncode
- HttpUtility.UrlEncodeUnicode
更新
问题是当我加密一个Guid并将其转换为base64字符串时,它将包含不安全的url字符。当然,当我试图导航到一个包含不安全字符的URL时,IIS(7.5/windows 7)就会炸毁。 Url对base64加密字符串进行编码会引发IIS错误(请求筛选模块被配置为拒绝包含双转义序列的请求)。我不知道它是如何检测双重编码的字符串,但它确实如此。
尝试上述方法对base64加密字符串进行编码后。我决定删除base64编码。但是,这会将加密文本留作字节[]。我尝试了UrlEncoding byte [],这是挂载httpUtility.Encode方法的重载之一。再次,虽然它是URL编码,但IIS不喜欢它,并提供了一个“找不到页面”。
在挖网之后,我碰到了一个HexEncoding/Decoding类。 将十六进制编码应用于加密的字节的技巧。输出是网址安全的。另一方面,我对解码和解密十六进制字符串没有任何问题。
我写了一个关于这个主题的短博客post,包括完整的源代码。
它使您能够加密和解密使用的是16字符密钥存储在查询字符串形式的数据:
我发现了一个伟大一套基类来解决这一点,但在大多数 部分可以归结为一个班级。此类需要某种类型的16位字符密钥 来执行加密和加密的值。如果需要,您还可以 设置到期值。
using System.Collections.Specialized;
using System.Security;
using System.Text;
using System.Web;
using EncryptionMVC.Security.Encryption.Utility.Interfaces;
using EncryptionMVC.Security.Encryption.Utility;
namespace Security.Encryption.QueryString
{
///
/// Provides a secure means for transfering data within a query string.
///
public class SecureQueryString : NameValueCollection
{
private string timeStampKey = '__TS__';
private string dateFormat = 'G';
private IEncryptionUtility mEncryptionUtil;
private DateTime m_expireTime = DateTime.MaxValue;
///
/// Creates an instance with a specified key.
///
/// The key used for cryptographic functions, required 16 chars in length.
public SecureQueryString(string key) : base()
{
mEncryptionUtil = new EncryptionUtility(key);
}
///
/// Creates an instance with a specified key and an encrypted query string.
///
/// The key used for cryptographic functions, required 16 chars in length.
/// An encrypted query string generated by a instance.
public SecureQueryString(string key, string queryString) : this(key)
{
Deserialize(DecryptAndVerify(queryString));
CheckExpiration();
}
///
/// Returns a encrypted query string.
///
///
public override string ToString()
{
return EncryptAndSign(Serialize());
}
private void Deserialize(string queryString)
{
string[] nameValuePairs = queryString.Split('&');
for (int i = 0; i <= nameValuePairs.Length - 1; i++) {
string[] nameValue = nameValuePairs(i).Split('=');
if (nameValue.Length == 2) {
base.Add(nameValue(0), nameValue(1));
}
}
if (base.GetValues(timeStampKey) != null) {
string[] strExpireTime = base.GetValues(timeStampKey);
m_expireTime = Convert.ToDateTime(strExpireTime(0));
}
}
private string Serialize()
{
StringBuilder sb = new StringBuilder();
foreach (string key in base.AllKeys) {
sb.Append(key);
sb.Append('=');
sb.Append(base.GetValues(key)(0).ToString());
sb.Append('&');
}
sb.Append(timeStampKey);
sb.Append('=');
sb.Append(m_expireTime.ToString(dateFormat));
return sb.ToString();
}
private string DecryptAndVerify(string input)
{
return mEncryptionUtil.Decrypt(input);
}
private string EncryptAndSign(string input)
{
return mEncryptionUtil.Encrypt(input);
}
private void CheckExpiration()
{
if (DateTime.Compare(m_expireTime, DateTime.Now) < 0) {
throw new ExpiredQueryStringException();
}
}
///
/// Gets or sets the timestamp in which this string should expire
///
public DateTime ExpireTime {
get { return m_expireTime; }
set { m_expireTime = value; }
}
}
}
要加密一些值,并将其传递到MVC另一个动作,你会 做类似下面。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection collection)
{
SecureQueryString qs = new SecureQueryString(mKey);
qs('YourName') = collection('name');
qs.ExpireTime = DateTime.Now.AddMinutes(2);
Response.Redirect('Home.aspx/About?data=' + HttpUtility.UrlEncode(qs.ToString()));
}
在我们重定向到,你就需要有这样相同的 键和查询字符串值本身进行解密的动作。请记住, 如果您没有正确的密钥,或者如果您在到期后尝试解密值 ,则该类将引发异常。
public ActionResult About()
{
if (Request('data') != null) {
try {
SecureQueryString qs = new SecureQueryString(mKey, Request('data'));
ViewData('Message') = 'Your name is ' + qs('YourName');
}
catch (Exception ex) {
}
}
return View();
}
我没有花太多时间来解释深入的来源,因为它具有 这么久,因为我写的。另外请记住,这是很长的 我的测试第一天...(但它似乎工作)
一如既往,此示例的source code可供下载。
加密和编码有区别;这些方法不适用于加密。
因为加密是很难得到正确,和令人难以置信的容易出错(同时还在寻找,就像“加密”为正确的解决方案),我建议你改用的GUID ID:
http://www.calemadr.com/.../ {6F0184E4- 809F-4e30-8A5B-4DC144135A54}
对于这种情况,SQL Server具有唯一标识符类型。
借调。如果目的只是混淆,那么在ID上使用加密没有意义。 – womp 2009-05-21 22:43:11
我的歉意,我在这个问题上不够详细。我正在尝试编码加密的字符串以确保URL安全。具有讽刺意味的是,我使用Guids,上面的加密是Guid。问题是编码加密的字符串,不会导致IIS发出安全警告或似乎是目录结构(包含斜线'/') @Womp - 由于系统的本质,我必须加密id 。 – 2009-05-21 23:02:12
嗯。那你为什么要加密GUID呢?如果您担心某个未经授权重复使用URL的用户,他们同样可以重复使用您提供的URL作为示例。如果你担心某人*猜测*别人的GUID ...永远不会发生。 – 2009-05-30 09:39:53
我很惊讶UrlEncode不起作用。你的加密输出是什么样的?
加密Guid后,尝试使用Convert.ToBase64String方法将其编码为Base64。然后,Url对Base64字符串进行编码,使其成为可接受的字符串,并将其包含在您的URL中。
不知道,如果它不再对你很重要,但我只是解决了我自己这个问题。我不得不加倍urlencode。
例如
Server.UrlEncode(Server.UrlEncode(串进行编码))
这个问题似乎是的Request.QueryString(编码的字符串)自动执行该拧了加密的译码。我希望我能更好地解释,但我仍然有点困惑
使用HttpServerUtility.UrlTokenEncode
和HttpServerUtility.UrlTokenDecode
将字节数组转换为URL安全字符串。
这篇文章可能比较老,但在这里你有另一种解决方案... 当你打算加密.ToBase64String时,url编码/解码会改变加密的字符串。
做解码之前,您encription库(或功能)试试这个:
Myencodedid.Replace(' ', '+')
,然后去解密..
首先,创建一个类是这样的:!
public class Encryption
{
public static string Encrypt(string clearText)
{
string EncryptionKey = "MAKV2SPBNI99212";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
public static string Decrypt(string cipherText)
{
string EncryptionKey = "MAKV2SPBNI99212";
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
}
在控制器中,添加这样的Ecription类的参考:
using testdemo.Models
public ActionResult Index() {
return View();
}
[HttpPost]
public ActionResult Index(string text)
{
if (Request["txtEncrypt"] != null)
{
string getEncryptionCode = Request["txtEncrypt"];
string DecryptCode = Encryption.Decrypt(HttpUtility.UrlDecode(getEncryptionCode));
ViewBag.GetDecryptCode = DecryptCode;
return View();
}
else {
string getDecryptCode = Request["txtDecrypt"];
string EncryptionCode = HttpUtility.UrlEncode(Encryption.Encrypt(getDecryptCode));
ViewBag.GetEncryptionCode = EncryptionCode;
return View();
}
}
在View:
<h2>Decryption Code</h2>
@using (Html.BeginForm())
{
<table class="table-bordered table">
<tr>
<th>Encryption Code</th>
<td><input type="text" id="txtEncrypt" name="txtEncrypt" placeholder="Enter Encryption Code" /></td>
</tr>
<tr>
<td colspan="2">
<span style="color:red">@ViewBag.GetDecryptCode</span>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" id="btnEncrypt" name="btnEncrypt"value="Decrypt to Encrypt code" />
</td>
</tr>
</table>
}
<br />
<br />
<br />
<h2>Encryption Code</h2>
@using (Html.BeginForm())
{
<table class="table-bordered table">
<tr>
<th>Decryption Code</th>
<td><input type="text" id="txtDecrypt" name="txtDecrypt" placeholder="Enter Decryption Code" /></td>
</tr>
<tr>
<td colspan="2">
<span style="color:red">@ViewBag.GetEncryptionCode</span>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" id="btnDecryt" name="btnDecryt" value="Encrypt to Decrypt code" />
</td>
</tr>
</table>
}
我希望这是有用的。
您的更新比回答更好。如果您希望Base64编码的URL安全,请阅读以下内容:http://*.com/a/10858198/237858 – kape123 2012-06-01 22:42:01