【问题标题】:How to encrypt the query string ID in MVC 4 ActionLink如何在 MVC 4 ActionLink 中加密查询字符串 ID
【发布时间】:2013-02-08 13:00:16
【问题描述】:

如何在ActionLink 中传递加密的 id。这是我写在我的view:

@model IEnumerable<forumAPP.tblTechnology>
@foreach (var item in Model)
{
string techName=item.TechName;
@Html.ActionLink(techName, "Details","Home", new { TopicID = item.TechID },null) // Here I would like to encrypt the TopicID
<br />
<br />
@Html.DisplayFor(modelItem => item.TechDesc)
}

【问题讨论】:

  • 你想用什么样的加密方式?
  • 任何类型的加密而不是将页面传输为http://localhost:1931/Home/Details?TopicID=1 我想要http://localhost:1931/Home/Details?TopicID=Ek7vP1YwVhc=

标签: asp.net-mvc-4


【解决方案1】:

这里有几个简单的方法可以用来编码/解码。 编码值不安全,如您所见,解码它是微不足道的。如果您的目标是混淆 id,这将起作用。如果你需要保护它,你应该采取不同的方法。

public string Encode( string encodeMe )
{
    byte[] encoded = System.Text.Encoding.UTF8.GetBytes( encodeMe );
    return Convert.ToBase64String( encoded );
}

public static string Decode( string decodeMe )
{
    byte[] encoded = Convert.FromBase64String( decodeMe );
    return System.Text.Encoding.UTF8.GetString( encoded );
}

因此您可以将这些方法放在您的控制器中,并使用 viewBag 将编码的 TechId 传递给视图

int techId = 1;
var encoded = Encode(id.ToString());
ViewBag.Encoded = encoded;

然后在你的链接中使用它

@Html.ActionLink(techName, "Details","Home", new { TopicID = ViewBag.Encoded },null)

(不过,您确实应该考虑使用视图模型。ViewBag 虽然是一种将数据传递给视图的方便且简单的方法,但并不被认为是最佳实践。熟悉视图模型和强类型视图将使您的mvc 的生活在未来会变得更容易。更不用说,为那些跟随你的人生成更清洁和更可维护的代码。)

【讨论】:

  • 我认为这段代码有问题,Convert.ToBase64String 可能会生成 (+) 符号(我可能/我也不确定)这些符号会导致 URL 出现问题
【解决方案2】:

添加一个包含两个类的文件夹

第 1 类:EncryptedActionParameterAttribute

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Web;
using System.Web.Mvc;

namespace MVCInvoicClient.Extensions
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class EncryptedActionParameterAttribute : ActionFilterAttribute
    {

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {

            Dictionary<string, object> decryptedParameters = new Dictionary<string, object>();
            if (HttpContext.Current.Request.QueryString.Get("q") != null)
            {
                string encryptedQueryString = HttpContext.Current.Request.QueryString.Get("q");
                string decrptedString = Decrypt(encryptedQueryString.ToString());
                string[] paramsArrs = decrptedString.Split('?');

                for (int i = 0; i < paramsArrs.Length; i++)
                {
                    string[] paramArr = paramsArrs[i].Split('=');
                    decryptedParameters.Add(paramArr[0], Convert.ToInt32(paramArr[1]));
                }
            }
            for (int i = 0; i < decryptedParameters.Count; i++)
            {
                filterContext.ActionParameters[decryptedParameters.Keys.ElementAt(i)] = decryptedParameters.Values.ElementAt(i);
            }
            base.OnActionExecuting(filterContext);

        }

        private string Decrypt(string encryptedText)
        {

                string key = "jdsg432387#";
                byte[] DecryptKey = { };
                byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
                byte[] inputByte = new byte[encryptedText.Length];

                DecryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                inputByte = Convert.FromBase64String(encryptedText);
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DecryptKey, IV), CryptoStreamMode.Write);
                cs.Write(inputByte, 0, inputByte.Length);
                cs.FlushFinalBlock();
                System.Text.Encoding encoding = System.Text.Encoding.UTF8;
                return encoding.GetString(ms.ToArray());
        }

    }
}

第 2 类:我的扩展

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCInvoicClient.Extensions
{
    public static class MyExtensions
    {
        public static MvcHtmlString EncodedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            string queryString = string.Empty;
            string htmlAttributesString = string.Empty;
            if (routeValues != null)
            {
                RouteValueDictionary d = new RouteValueDictionary(routeValues);
                for (int i = 0; i < d.Keys.Count; i++)
                {
                    if (i > 0)
                    {
                        queryString += "?";
                    }
                    queryString += d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
                }
            }

            if (htmlAttributes != null)
            {
                RouteValueDictionary d = new RouteValueDictionary(htmlAttributes);
                for (int i = 0; i < d.Keys.Count; i++)
                {
                    htmlAttributesString += " " + d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
                }
            }

            //<a href="/Answer?questionId=14">What is Entity Framework??</a>
            StringBuilder ancor = new StringBuilder();
            ancor.Append("<a ");
            if (htmlAttributesString != string.Empty)
            {
                ancor.Append(htmlAttributesString);
            }
            ancor.Append(" href='");
            if (controllerName != string.Empty)
            {
                ancor.Append("/" + controllerName);
            }

            if (actionName != "Index")
            {
                ancor.Append("/" + actionName);
            }
            if (queryString != string.Empty)
            {
                ancor.Append("?q=" + Encrypt(queryString));
            }
            ancor.Append("'");
            ancor.Append(">");
            ancor.Append(linkText);
            ancor.Append("</a>");
            return new MvcHtmlString(ancor.ToString());
        }

        private static string Encrypt(string plainText)
        {
            string key = "jdsg432387#";
            byte[] EncryptKey = { };
            byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
            EncryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByte = Encoding.UTF8.GetBytes(plainText);
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(EncryptKey, IV), CryptoStreamMode.Write);
            cStream.Write(inputByte, 0, inputByte.Length);
            cStream.FlushFinalBlock();
            return Convert.ToBase64String(mStream.ToArray());
        }               
    }
}

控制器

Add this line above the controller class Example for your Index
 [EncryptedActionParameter]

在你看来

 @Html.EncodedActionLink("Download Invoice", "FileDownload","DataFiles", new { id = item.DataFilesID }, null)

添加 using 语句

@using MVCInvoicClient.Extensions

【讨论】:

  • 你真的应该使用HttpUtility.ParseQueryString (documentation) 而不是手动解析它。
  • 在属性中,我建议更改以下内容,使其适用于任何参数类型,而不仅仅是 int:在 string[] paramsArrs = decrptedString.Split('?');输入以下行: var paramInfos = ((ReflectedActionDescriptor)filterContext.ActionDescriptor).MethodInfo.GetParameters(); 在 for 循环中我会这样做: var paramArr = paramArrs[i] .Split('='); var paramInfo = paramInfos.First(x =&gt; x.Name == paramArr[0]); var paramType = paramInfo.ParameterType; decryptedParameters.Add(paramArr[0], Convert.ChangeType(paramArr[1], paramType));
【解决方案3】:

我在寻找一种安全的方法时遇到了这个问题。如果其他人希望安全地执行此操作,您可以使用 MvcSerializer(我在 MVC futures 3 项目中找到了它,我不确定它是否包含在 MVC 4 中)。例如:

(new MvcSerializer()).Serialize(<Your data here>, SerializationMode.EncryptedAndSigned)

然后把这个过程倒过来……

(new MvcSerializer()).Deserialize(<Serialized data here>, SerializationMode.EncryptedAndSigned)

这很棒,因为它无需任何额外的努力即可对数据进行加密和签名。 futures 项目还包括一些属性,可以在模型绑定期间自动发生这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多