用httpmodule自动加密解密query string查询字符串

项目中经常遇到query string的加密解密问题,如果在页面或者page base里面处理的话总有点不爽。
所以最近尝试着用httpmodule解决。在网上看到了几篇文章,综合了一下,解决了postback加密过的url丢失的问题。

环境asp.net 2.0

 

更新于2008-12-31:

楼下有人说不行,我试了一下可以,可能测的不全,如果哪位发现有错误麻烦发个用例代码给我,谢谢!

我的测试打包代码/Files/beyondjay/WebSiteHttpModule.zip

HttpModule:
#region Using

using System;
using System.IO;
using System.Web;
using System.Text;
using System.Security.Cryptography;

#endregion

/// <summary>
/// Summary description for QueryStringModule
/// </summary>
public class QueryStringModule : IHttpModule
{

    #region IHttpModule Members

    public void Dispose()
    {
        // Nothing to 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";

    void context_BeginRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;
        if (context.Request.Url.OriginalString.Contains("aspx") && context.Request.RawUrl.Contains("?"))
        {
            string query = ExtractQuery(context.Request.Url.ToString());
            string path = GetVirtualPath();

            if (query.StartsWith(PARAMETER_NAME, StringComparison.OrdinalIgnoreCase))
            {
                // Decrypts the query string and rewrites the path.
                context.Items["OriginalUrl"] = context.Request.Url.ToString();
                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.Items["OriginalUrl"] = path + encryptedQuery;
                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>
    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>
    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

}


PageBase:需要继承一下这个pagebase
public class PageBase:Page
    {

        protected override void OnLoadComplete(EventArgs e)
        {
            string originalUrl = Context.Items["OriginalUrl"] as string;

            if (!string.IsNullOrEmpty(originalUrl)) //So this page have been urlrewriten, after the page onloaded, rewrite the url of this page to original url
            {
                string query = string.Empty;
                int pos = originalUrl.IndexOf('?');
                if (pos >= 0)// check if has query paramet
                    query = originalUrl.Substring(pos + 1);
                //                    originalUrl = originalUrl.Substring(0, pos);
                Context.RewritePath(QueryStringModule.GetVirtualPath(), string.Empty, query);
            }
            base.OnLoadComplete(e);
        }
    }


参考
http://msdn.microsoft.com/en-us/library/ms972974.aspx
http://www.webpronews.com/expertarticles/2007/01/25/aspnet-httpmodule-for-query-string-encryption

posted @ 2008-06-06 17:46  helloworld22  阅读(1427)  评论(3)    收藏  举报