65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 查询字符串加密

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.90/5 (28投票s)

2008年4月30日

CPOL

2分钟阅读

viewsIcon

254207

downloadIcon

4236

明文查询字符串对您的 Web 应用程序构成潜在的安全威胁。因此,查询字符串应始终加密。

引言

使用查询字符串从浏览器向服务器发送数据是一种广泛采用的方法。允许 Web 应用程序的访问者修改以明文形式传输的查询字符串,无疑是一种潜在的安全威胁。

因此,我鼓励开发人员加密查询字符串,即使它们不包含机密数据。但是,我知道仍然可以篡改加密的查询字符串,但通过适当的异常处理,这是无害的。

背景

为了使本文简单易懂,我使用了可破解的加密方法(DES 编码),尽管任何最先进的加密方法都可以轻松应用于给定的示例。

使用代码

那么,让我们开始吧。所提供解决方案的主要部分是一个 HttpModule,它解密查询字符串,从而为页面请求提供普通的未加密查询字符串。

using System;
using System.Web;
using System.Web.Configuration;

namespace HelveticSolutions.QueryStringEncryption
{
    /// <summary>
    /// Http module that handles encrypted query strings.
    /// </summary>
    public class CryptoQueryStringUrlRemapper : IHttpModule
    {
        #region IHttpModule Members

        /// <summary>
        /// Initialize the http module.
        /// </summary>
        /// <param name="application">Application,
        ///           that called this module.</param>
        public void Init(HttpApplication application)
        {
            // Attach the acquire request state event
            // to catch the encrypted query string
            application.AcquireRequestState += application_AcquireRequestState;
        }

        public void Dispose()
        {}
    
        #endregion

        /// <summary>
        /// Event, that is called when the application acquires the request state.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void application_AcquireRequestState(object sender, EventArgs e)
        {
            // Get http context from the caller.
            HttpApplication application = (HttpApplication) sender;
            HttpContext context = application.Context;

            // Check for encrypted query string
            string encryptedQueryString = context.Request.QueryString["request"];
            if (!string.IsNullOrEmpty(encryptedQueryString))
            {
                // Decrypt query strings
                string cryptoKey = WebConfigurationManager.AppSettings["CryptoKey"];
                string decryptedQueryString = 
                  CryptoQueryStringHandler.DecryptQueryStrings(encryptedQueryString, 
                                                               cryptoKey);
                context.Server.Transfer(
                  context.Request.AppRelativeCurrentExecutionFilePath + 
                  "?" + decryptedQueryString);
            }
        }
    }
}

正如您可能注意到的,如果当前请求存在加密的查询字符串,该模块将自动终止当前页面的执行,并在服务器上内部启动新的请求执行。

下一步是在 web.config 文件中注册 HttpModule

<httpModules>
    <add name="CryptoQueryStringUrlRemapper" 
      type="HelveticSolutions.QueryStringEncryption.CryptoQueryStringUrlRemapper"/>
</httpModules>

最后但并非最不重要的一点,不要忘记在将其发送回服务器之前加密查询字符串。

private void PrepareSendButton()
{
    NameValueCollection queryStrings = new NameValueCollection();
    queryStrings.Add("param1", "Test1");
    queryStrings.Add("param2", "Test2");
    queryStrings.Add("param3", "Test3");

    // Encrypt query strings
    string encryptedString = CryptoQueryStringHandler.EncryptQueryStrings(
      queryStrings, WebConfigurationManager.AppSettings["CryptoKey"]);
    btnSendParams.PostBackUrl = string.Concat("~/Default.aspx?", encryptedString);
}

如本文前面所述,加密类可以轻松地替换为任何其他加密类。可以从上方下载一个完整的运行示例。

重要问题

CryptoQueryStringHandler 中的 DecryptQueryStrings 方法包含以下行

return Encryption64.Decrypt(encryptedStrings.Replace(" ", "+"), key); 

出于未知原因,请求会将查询中的每个 '+' 字符替换为空字符。

历史

  • 2008 年 4 月 30 日 - 第一个版本(已删除 -> 无法修改,无论出于何种原因……)。
  • 2008 年 5 月 1 日 - 重新发布更新后的文章。
  • 2008 年 5 月 8 日 - 为了支持 Session 数据,将 HttpModule 中的 BeginRequest 事件更改为 AcquireRequestState
  • 2014 年 11 月 11 日 - 更正了命名空间
© . All rights reserved.