在ASP.NET MVC中的URL中加密一个id [英] Encrypting an id in an URL in ASP.NET MVC

查看:75
本文介绍了在ASP.NET MVC中的URL中加密一个id的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Url中对加密的ID进行编码。像这样: http://www.calemadr.com/Membership/Welcome/9xCnCLIwzxzBuPEjqJFxC6XJdAZqQsIDqNrRUJoW6229IIeeL4eXl5n1cnYapg + N



但是,它无法正确编码,而是在加密中加上/,或者我收到错误IIS:请求过滤模块被配置为拒绝包含双转义序列的请求。



我尝试过不同的编码,每个都失败:




  • HttpUtility.HtmlEncode

  • HttpUtility.UrlEncode

  • HttpUtility.UrlPathEncode

  • HttpUtility.UrlEncodeUnicode



更新 / p>

问题是当我加密了一个Guid并将其转换为base64字符串,它将包含不安全的url字符。当然,当我试图导航到包含不安全的字符的网址IIS(7.5 / Windows 7)将会爆炸。 URL编码base64加密的字符串将在IIS中引发错误(请求过滤模块配置为拒绝包含双转义序列的请求。)。我不知道如何检测到双重编码的字符串,但它确实。



尝试以上方法对base64加密字符串进行编码。我决定删除base64编码。但是,将加密文本留作字节[]。我尝试UrlEncoding字节[],它是挂起httpUtility.Encode方法之一的重载之一。再次,当它是URL编码时,IIS不喜欢它,并提供一个没有找到的页面。



在挖掘网络之后我遇到了一个 HexEncoding / Decoding 课程。
将十六进制编码应用于加密的字节做了一个技巧。输出是url的安全。另一方面,我没有解码和解密十六进制字符串的任何问题。

解决方案

我写了一个短的博客 post 关于这个主题,包括完整的源代码。



它使您能够使用16个字符密钥加密和解密以查询字符串形式存储的数据:


我发现了一大堆基础类来解决这个问题,但是最多的
部分归结为一个类。这个类需要一个
的16个字符键来进行加密和加密的值。如果需要,您也可以
设置到期值。




  using System.Collections 。专门; 
使用System.Security;
使用System.Text;
使用System.Web;
使用EncryptionMVC.Security.Encryption.Utility.Interfaces;
使用EncryptionMVC.Security.Encryption.Utility;
命名空间Security.Encryption.QueryString
{
///
///提供用于在查询字符串中传输数据的安全方法。
///
public class SecureQueryString:NameValueCollection
{

private string timeStampKey ='__TS__';
private string dateFormat ='G';
private IEncryptionUtility mEncryptionUtil;
private DateTime m_expireTime = DateTime.MaxValue;

///
///使用指定的键创建一个实例。
///
///用于加密功能的密钥,长度为16个字符。
public SecureQueryString(string key):base()
{
mEncryptionUtil = new EncryptionUtility(key);
}

///
///使用指定的密钥和加密的查询字符串创建一个实例。
///
///用于加密功能的密钥,长度为16个字符。
///由实例生成的加密查询字符串。
public SecureQueryString(string key,string queryString):this(key)
{
反序列化(DecryptAndVerify(queryString));
CheckExpiration();
}

///
///返回加密的查询字符串。
///
///
public override string ToString()
{
return EncryptAndSign(Serialize());
}

private void Deserialize(string queryString)
{
string [] nameValuePairs = queryString.Split('&'); (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();
}
}

///
///获取或设置此字符串到期的时间戳
///
public DateTime ExpireTime {
get {return m_expireTime; }
set {m_expireTime = value; }
}
}
}




要加密一些值并将其传递给MVC中的另一个操作,您将
执行如下操作。




  [AcceptVerbs(HttpVerbs.Post)] 
public ActionResult索引(FormCollection集合)
{
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关于()
{
if(Request('data')!= null){
try {
SecureQueryString qs = new SecureQueryString(mKey,Request('data'));

ViewData('Message')='你的名字是'+ qs('YourName');
}
catch(Exception ex){

}
}
return View();
}




我没有花太多时间解释源自深度,因为它有
已经这么久,因为我写了它。还要记住,这是很久以前
我的测试第一天...(但它似乎工作)



与往常一样,源代码



I'm attempting to encode the encrypted id in the Url. Like this: http://www.calemadr.com/Membership/Welcome/9xCnCLIwzxzBuPEjqJFxC6XJdAZqQsIDqNrRUJoW6229IIeeL4eXl5n1cnYapg+N

However, it either doesn't encode correctly and I get slashes '/' in the encryption or I receive and error from IIS: The request filtering module is configured to deny a request that contains a double escape sequence.

I've tried different encodings, each fails:

  • HttpUtility.HtmlEncode
  • HttpUtility.UrlEncode
  • HttpUtility.UrlPathEncode
  • HttpUtility.UrlEncodeUnicode

Update

The problem was I when I encrypted a Guid and converted it to a base64 string it would contain unsafe url characters . Of course when I tried to navigate to a url containing unsafe characters IIS(7.5/ windows 7) would blow up. Url Encoding the base64 encrypted string would raise and error in IIS (The request filtering module is configured to deny a request that contains a double escape sequence.). I'm not sure how it detects double encoded strings but it did.

After trying the above methods to encode the base64 encrypted string. I decided to remove the base64 encoding. However this leaves the encrypted text as a byte[]. I tried UrlEncoding the byte[], it's one of the overloads hanging off the httpUtility.Encode method. Again, while it was URL encoded, IIS did not like it and served up a "page not found."

After digging around the net I came across a HexEncoding/Decoding class. Applying the Hex Encoding to the encrypted bytes did the trick. The output is url safe. On the other side, I haven't had any problems with decoding and decrypting the hex strings.

解决方案

I wrote a short blog post about this very topic including full source code.

It enables you to encrypt and decrypt data stored in query string form using a 16 char key :

I found a great set of base classes to solve this but for the most part it comes down to one class. This class requires a 16 char key of some kind to do the encryption and a value to encrypt. You can also set an expiration value if needed.

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; }
        }
    }
}

To encrypt some value and pass it to another action in MVC you would do something like the below.

[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()));
}

In the action that we redirect to, you would need to have this same key and the query string value itself to decrypt it. Keep in mind that if you don't have the correct key or if you try to decrypt the value after the expiration, the class will throw an exception.

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();
}

I didn't spend much time explaining the source in depth because it has been so long since I wrote it. Also keep in mind this was long before my test first days ... (but it does appear to work)

As always, the source code for this sample is available for download.

这篇关于在ASP.NET MVC中的URL中加密一个id的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆