我需要在我的ASP.NET MVC应用程序中加密URL。
我是否需要在全局页面中的路由集合中编写代码以加密所有URL?
我需要在我的ASP.NET MVC应用程序中加密URL。
我是否需要在全局页面中的路由集合中编写代码以加密所有URL?
<system.web>
<httpModules>
<add name="URIHandler" type="URIHandler" />
</httpModules>
II7
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="URIHandler" />
<add name="URIHandler" type="URIHandler" />
</modules>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics.CodeAnalysis;
public class URIHandler : IHttpModule
{
#region IHttpModule members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
#endregion
private const string PARAMETER_NAME = "enc=";
private const string ENCRYPTION_KEY = "key";
private void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
//if (context.Request.Url.OriginalString.Contains("aspx") && context.Request.RawUrl.Contains("?"))
if (context.Request.RawUrl.Contains("?"))
{
string query = ExtractQuery(context.Request.RawUrl);
string path = GetVirtualPath();
if (query.StartsWith(PARAMETER_NAME, StringComparison.OrdinalIgnoreCase))
{
// Decrypts the query string and rewrites the path.
string rawQuery = query.Replace(PARAMETER_NAME, string.Empty);
string decryptedQuery = Decrypt(rawQuery);
context.RewritePath(path, string.Empty, decryptedQuery);
}
else if (context.Request.HttpMethod == "GET")
{
// Encrypt the query string and redirects to the encrypted URL.
// Remove if you don't want all query strings to be encrypted automatically.
string encryptedQuery = Encrypt(query);
context.Response.Redirect(path + encryptedQuery);
}
}
}
/// <summary>
/// Parses the current URL and extracts the virtual path without query string.
/// </summary>
/// <returns>The virtual path of the current URL.</returns>
private static string GetVirtualPath()
{
string path = HttpContext.Current.Request.RawUrl;
path = path.Substring(0, path.IndexOf("?"));
path = path.Substring(path.LastIndexOf("/") + 1);
return path;
}
/// <summary>
/// Parses a URL and returns the query string.
/// </summary>
/// <param name="url">The URL to parse.</param>
/// <returns>The query string without the question mark.</returns>
private static string ExtractQuery(string url)
{
int index = url.IndexOf("?") + 1;
return url.Substring(index);
}
#region Encryption/decryption
/// <summary>
/// The salt value used to strengthen the encryption.
/// </summary>
private readonly static byte[] SALT = Encoding.ASCII.GetBytes(ENCRYPTION_KEY.Length.ToString());
/// <summary>
/// Encrypts any string using the Rijndael algorithm.
/// </summary>
/// <param name="inputText">The string to encrypt.</param>
/// <returns>A Base64 encrypted string.</returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static string Encrypt(string inputText)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
byte[] plainText = Encoding.Unicode.GetBytes(inputText);
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(ENCRYPTION_KEY, SALT);
using (ICryptoTransform encryptor = rijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16)))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainText, 0, plainText.Length);
cryptoStream.FlushFinalBlock();
return "?" + PARAMETER_NAME + Convert.ToBase64String(memoryStream.ToArray());
}
}
}
}
/// <summary>
/// Decrypts a previously encrypted string.
/// </summary>
/// <param name="inputText">The encrypted string to decrypt.</param>
/// <returns>A decrypted string.</returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static string Decrypt(string inputText)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
byte[] encryptedData = Convert.FromBase64String(inputText);
PasswordDeriveBytes secretKey = new PasswordDeriveBytes(ENCRYPTION_KEY, SALT);
using (ICryptoTransform decryptor = rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16)))
{
using (MemoryStream memoryStream = new MemoryStream(encryptedData))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainText = new byte[encryptedData.Length];
int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
return Encoding.Unicode.GetString(plainText, 0, decryptedCount);
}
}
}
}
#endregion
}
https://www.codeproject.com/questions/1036066/how-to-hide-url-parameter-asp-net-mvc
https://msdn.microsoft.com/en-us/library/aa719858(v=vs.71).aspx
?
的 URL 很有效。如果没有 ?
传递 ID,你会如何加密呢?例如:myDomain/myController/myAction/10
而不是:myDomain/myController/myAction?myID=10
- DNKROZ/
前的所有数字值),但是我注意到有人可以使用F12开发工具在视图中更改ID参数,然后在加密之前成功操作URL。因此,我不得不放弃上面的解决方案,并正在实施另一个解决方案,该解决方案涉及扩展 ActionLink
。 我正在使用 https://www.codeproject.com/Articles/130588/Preventive-Method-for-URL-Request-Forgery-An-Examp 作为参考。 - DNKROZ您可以创建自定义的HTML助手来加密查询字符串,并使用自定义操作过滤器属性进行解密和获取原始值。您可以全局实现它,这样不会花费太多时间。您可以参考这里Asp.Net MVC中的URL加密。这将帮助您使用自定义助手和自定义操作过滤器属性。
全局加密所有URL参数(查询字符串)可能是没有意义的。大多数参数都是HttpGet使用的显示项。如果全部加密,那么这将不能生成非常信息化的页面。但是,如果有一些敏感参数仅在客户端上隐藏字段(键),最终返回给服务器以识别记录,则可能值得加密。
考虑此viewModel:
public viewModel
{
public int key {get;set;} // Might want to encrypt
public string FirstName {get;set;} // Don't want this encrypted
public string LastName {get;set;} // Don't want this encrypted
}
viewModel会被转换成一个查询字符串,类似于...appName.com/index?Id=2;FirstName="John";LastName="Doe"
如果将此viewModel作为查询字符串传递,那么加密名字的意义何在?
需要注意的是,查询字符串是HttpGet。HttpPost使用会话来传递值而不是查询字符串。 HttpPost会话是加密的。但是,HttpPost有开销。因此,如果您的页面确实包含需要显示的敏感数据(例如用户当前密码),则考虑改用HttpPost。