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

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

问题描述

我试图连接code在URL加密ID。像这样的: <一个href=\"http://www.calemadr.com/Membership/Welcome/9xCnCLIwzxzBuPEjqJFxC6XJdAZqQsIDqNrRUJoW6229IIeeL4eXl5n1cnYapg+N\">http://www.calemadr.com/Membership/Welcome/9xCnCLIwzxzBuPEjqJFxC6XJdAZqQsIDqNrRUJoW6229IIeeL4eXl5n1cnYapg+N

但是,它要么不带code正确,我也得到了加密斜杠/或者我接受和IIS错误:请求筛选模块被配置为拒绝包含的请求双转义序列。

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


  • HttpUtility.HtmlEn code

  • HttpUtility.UrlEn code

  • HttpUtility.UrlPathEn code

  • HttpUtility.UrlEn $ C $铜镍code

更新

问题是我,当我加密​​一个GUID,并将其转换成一个base64字符串,它将包含不安全的URL字符。当然,当我试图浏览到包含不安全字符的URL IIS(7.5 / Windows 7中)将炸毁。 URL编码在IIS加密的字符串将提高和错误中的Base64(的请求筛选模块被配置为拒绝包含一个双转义序列的请求。的)。我不知道它是如何检测出双带codeD字符串,但是它没有。

在尝试上述方法EN code加密的字符串以base64后。我决定删除base64编码。然而,这留下加密后的文本作为一个byte []。我试图URL编码的字节[],它的重载悬挂在httpUtility.En code方法之一。同样,虽然它是URL连接codeD,IIS不喜欢它,并担任了的找不到网页。

我身边穿过 HexEncoding /解码类。
运用十六进制编码为加密字节的伎俩。输出是URL安全的。在另一边,我还没有与解码和解密十六进制字符串的任何问题。


解决方案

我写了一个简短博客的帖子关于这个题目,包括完整的源$ C ​​$ C。

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


  

我发现了一个伟大一套基类来解决这个问题,但为最
  分手它归结为一个类。这个类需要一个16字符键
  一些做加密和加密值。你也可以
  如果需要设置到期值。


 使用System.Collections.Specialized;
使用System.Security;
使用System.Text;
使用的System.Web;
使用EncryptionMVC.Security.Encryption.Utility.Interfaces;
使用EncryptionMVC.Security.Encryption.Utility;
命名空间Security.Encryption.QueryString
{
    ///
    ///提供用于查询字符串中传输数据的安全方法。
    ///
    公共类SecureQueryString:NameValueCollection中
    {        私人字符串timeStampKey ='__TS__';
        私人字符串DATEFORMAT ='G';
        私人IEncryptionUtility mEncryptionUtil;
        私人的DateTime m_expireTime = DateTime.MaxValue;        ///
        ///创建一个具有指定键的实例。
        ///
        ///用于加密功能的关键,需要在长度为16个字符。
        公共SecureQueryString(字符串键):基地()
        {
            mEncryptionUtil =新EncryptionUtility(密钥);
        }        ///
        ///创建一个具有指定密钥和加密查询字符串的实例。
        ///
        ///用于加密功能的关键,需要在长度为16个字符。
        ///一个实例生成一个加密的查询字符串。
        公共SecureQueryString(字符串键,字符串的queryString):这(键)
        {
            反序列化(DecryptAndVerify(的queryString));
            CheckExpiration();
        }        ///
        ///返回一个加密的查询字符串。
        ///
        ///
        公共重写字符串的ToString()
        {
            返回EncryptAndSign(序列化());
        }        私人无效反序列化(字符串的queryString)
        {
            字符串[] = namevaluepairs中queryString.Split('和;');
            的for(int i = 0; I&LT; = nameValuePairs.Length - 1;我++){
                字符串[] = nameValue namevaluepairs中(I).Split('=');
                如果(nameValue.Length == 2){
                    base.Add(nameValue(0),nameValue(1));
                }
            }            如果(base.GetValues​​(timeStampKey)!= NULL){
                字符串[] = strExpireTime base.GetValues​​(timeStampKey);
                m_expireTime = Convert.ToDateTime(strExpireTime(0));
            }
        }        私人字符串序列化()
        {
            StringBuilder的SB =新的StringBuilder();
            的foreach(在base.AllKeys字符串键){
                sb.Append(键);
                sb.Append(=);
                sb.Append(base.GetValues​​(密钥)(0)的ToString());
                sb.Append('和;');
            }            sb.Append(timeStampKey);
            sb.Append(=);
            sb.Append(m_expireTime.ToString(日期格式));            返回sb.ToString();
        }        私人字符串DecryptAndVerify(字符串输入)
        {
            返回mEncryptionUtil.Decrypt(输入);
        }        私人字符串EncryptAndSign(字符串输入)
        {
            返回mEncryptionUtil.Encrypt(输入);
        }        私人无效CheckExpiration()
        {
            如果(DateTime.Compare(m_expireTime,DateTime.Now)小于0){
                抛出新ExpiredQueryStringException();
            }
        }        ///
        ///获取或设置在此字符串应到期的时间戳
        ///
        公众的DateTime ExpireTime {
            {返回m_expireTime; }
            集合{m_expireTime =价值; }
        }
    }
}


  

要加密一定的价值,并把它传递给MVC中你会另一个动作
  像做下面的。


 的[AcceptVerbs(HttpVerbs.Post)
公众的ActionResult指数(的FormCollection集合)
{
    SecureQueryString QS =新SecureQueryString(MKEY);    QS('YOURNAME')=集合('名');
    qs.ExpireTime = DateTime.Now.AddMinutes(2);    的Response.Redirect(Home.aspx /关于数据=?'+ HttpUtility.UrlEn code(qs.ToString()));
}


  

在我们重定向到的动作,你就需要有这样相同
  键和查询字符串值本身进行解密。请记住,
  如果你没有正确的密钥,或者如果你试图解密值
  到期后,班会抛出异常。


 公众的ActionResult关于()
{
    如果(请求(数据)!= NULL){
        尝试{
            SecureQueryString QS =新SecureQueryString(MKEY,请求(数据));            ViewData的('信息')='你的名字是'+ QS('提供yourname');
        }
        赶上(例外前){        }
    }
    返回查看();
}


  

我没有花太多时间来解释源深,因为它有
  这么长时间,因为我写的。记还留着,这是很久以前
  我测试的第一天... ...(但它似乎工作)


  
  

一如既往,为源$ C ​​$ C 此示例是可供下载。


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天全站免登陆