【发布时间】:2015-08-18 00:12:11
【问题描述】:
我希望在查询字符串中加密和解密模型 ID 的参数。我已经阅读了几种不同的方法,但有些文章有点过时了。加密查询字符串的最佳方法是什么?
我已按照本文 [http://www.dotnettrace.net/2013/09/encrypt-and-decrypt-url-in-mvc-4.html],也在此 SO 问题中引用的方法中概述的方法进行了操作。 Encrypt Route Data in URL.
我的编码操作链接正常工作,但我不知道如何在我的控制器的重定向操作中使用相同的加密 ID。
我使用的方法是最好的方法吗?我想防止用户更改查询字符串中的 ID 以查看另一条记录。
//extension
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);
}
}
object newRouteValues = new { q = Encrypt(queryString) };
string url = UrlHelper.GenerateUrl(null, actionName, controllerName, null, null, null, new RouteValueDictionary(newRouteValues), htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true);
TagBuilder tagBuilder = new TagBuilder("a")
{
InnerHtml = (!String.IsNullOrEmpty(linkText)) ? HttpUtility.HtmlEncode(linkText) : String.Empty
};
tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
tagBuilder.MergeAttribute("href", url);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
private static string Encrypt(string plainText)
{
string key = "@m2qJzeyjXLBK!axPV$Bvg3QUP";
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());
}
//attribute
[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 = "@m2qJzeyjXLBK!axPV$Bvg3QUP";
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());
}
}
此 EncodedActionLink 正在按预期工作:
@Html.EncodedActionLink("Add Log", "CreateLog", "Logs", new { id = Model.id }, new { @class = "btn btn-success btn-xs" })
如何在控制器中加密 id?
return RedirectToAction("Details", "Log", new { id = ENCRYPTEDIDHERE})
更新 ===
我应该添加 id 不是用户 ID。控制器已经在检查用户是否已登录并有权查看通话记录。
【问题讨论】:
-
您是否考虑过,即使用户能够猜测属于另一个用户的资源的 id,系统也应该检查该用户是否应该有权访问该资源并返回
403(或404,或您认为合适的任何代码)如果他们不应该访问?这是为了缓解不安全的直接对象引用攻击owasp.org/index.php/… -
为什么? (任何人都可以在地址栏中输入他们想要的任何内容)。如果用户无权访问具有该 ID 的项目,则抛出错误。
-
加密在那里几乎毫无意义——只是不可猜测的、非顺序的 ID(如 Guid)应该以更低的成本/复杂性提供等效的保护。其余的应该通过适当的身份验证/授权来完成,例如建议cacho's answer
-
有效积分。也许我只是把事情复杂化了。我的角色已经到位。
标签: c# asp.net-mvc encryption