在ASP.NET MVC中加密URL中的id

Chu*_*way 11 encryption asp.net-mvc

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

但是,它要么没有正确编码,我在加密中得到斜杠"/",或者我收到来自IIS的错误:请求过滤模块配置为拒绝包含双转义序列的请求.

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

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

更新

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

尝试上述方法后编码base64加密字符串.我决定删除base64编码.但是,这会将加密文本保留为byte [].我尝试了UrlEncoding byte [],这是挂起httpUtility.Encode方法的重载之一.同样,虽然它是URL编码,但IIS不喜欢它,并提供了"找不到页面".

在网上挖掘后,我遇到了一个HexEncoding/Decoding类.将Hex编码应用于加密字节就可以了.输出是url安全的.另一方面,我对解码和解密十六进制字符串没有任何问题.

Pav*_*uva 10

使用HttpServerUtility.UrlTokenEncodeHttpServerUtility.UrlTokenDecode将字节数组转换为URL安全字符串.

请参阅C#Byte []到Url Friendly String.


Tor*_*ups 7

我写了一篇关于这个主题的简短博客文章,包括完整的源代码.

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

我发现了一组很好的基类来解决这个问题,但是大多数情况下它归结为一个类.此类需要使用某种16 char键进行加密,并需要加密值.如果需要,您还可以设置到期值.

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; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要加密某个值并将其传递给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()));
}
Run Code Online (Sandbox Code Playgroud)

在我们重定向到的操作中,您需要使用相同的密钥和查询字符串值来解密它.请记住,如果您没有正确的密钥,或者在过期后尝试解密该值,则该类将抛出异常.

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();
}
Run Code Online (Sandbox Code Playgroud)

我没有花太多时间深入解释源代码,因为我写这篇文章的时间已经很久了.还要记住,这是在我的测试第一天之前很久......(但它似乎确实有效)

与往常一样,此示例的源代码可供下载.