日期:2011-01-15 浏览次数:20628 次
浏览器的会话使用存储在 SessionID 属性中的唯一标识符进行标识。会话 ID 使 ASP.NET 应用程序能够将特定的浏览器与 Web 服务器上相关的会话数据和信息相关联。会话 ID 的值在浏览器和 Web 服务器间通过 Cookie 进行传输,如果指定了无 Cookie 会话,则通过 URL 进行传输。
ASP.NET 通过自动在页的 URL 中插入唯一的会话 ID 来保持无 Cookie 会话状态。例如,下面的 URL 已被 ASP.NET 修改,以包含唯一的会话 ID lit3py55t21z5v55vlm25s55:
http://www.example.com/s(lit3py55t21z5v55vlm25s55)/orderform.aspx
如果一个包含无 Cookie SessionID 的链接被多个浏览器共享时(可能通过搜索引擎或其他程序),此行为可能导致对会话数据的意外共享。可以通过禁用会话标识符的回收来降低多个客户端共享会话数据的可能性。为此,将 sessionState 配置元素的 regenerateExpiredSessionId 属性设置为 true。这样,在使用已过期的会话 ID 发起无 Cookie 会话请求时,将生成一个新的会话 ID。
——摘自 MSDN
.NET2.0中我们已可以通过重写SessionIDManager 类来改变SessionID 的生成机制和验证方法来防止会话数据的意外共享(即出现多个浏览器被识别为同一个会话,共用一个Session),可在.NET1.1中却没有相关的类让我们改变SessionID 的生成机制(封装死了),但受一篇文章的启发,我们可以在SessionID 生成之后对它进行处理。文章是老外写的,由于本人阅读能力有限,偶可没时间去看一大版唧唧歪歪的鹰文,直接下了代码来看。还好代码不算多,思路也很清晰,大概了解了他实现重写SessionID的原理,我改了下在无Cookie 会话中完美实现了。
相关代码
using System;
using System.Web;
using System.Web.SessionState;
using System.Web.Security;
using System.Configuration;
using System.Security.Cryptography;
using System.Runtime.Serialization;
using System.Globalization;
using System.Text;
public class SecureSessionModule : IHttpModule
{
private static string _ValidationKey = null;
public void Init (HttpApplication app)
{
if (_ValidationKey == null)
_ValidationKey = GetValidationKey ();
app.AcquireRequestState+=new EventHandler(app_AcquireRequestState);
}
void app_AcquireRequestState (Object sender, EventArgs e)
{
_ValidationKey=GetValidationKey();//每天生成一个KEY提高安全性
HttpContext current = ((HttpApplication) sender).Context;
//将处理后的SessionID存在Session["ASP.NET_SessionID"]中
string sessionid = GetSession (current, "ASP.NET_SessionID");
if (sessionid != null)
{
if (sessionid.Length <= 24)
RedirectUrl(current);
string id = sessionid.Substring (0, 24);
string mac1 = sessionid.Substring (24);
string mac2 = GetSessionIDMac (id, current.Request.UserHostAddress, current.Request.UserAgent, _ValidationKey);
// 用户客户端信息发生的变化,比对失败
&nbs