簡(jiǎn)要介紹,本文主要內(nèi)容是實(shí)現(xiàn)通過ASP.NET自己的Sql Server的Session存儲(chǔ)機(jī)制實(shí)現(xiàn),通過存儲(chǔ)過程實(shí)現(xiàn)忽略程序標(biāo)識(shí)的區(qū)別,達(dá)到多程序池間Session數(shù)據(jù)共享的目的。詳細(xì)原文:
本文轉(zhuǎn)載人數(shù)己經(jīng)太多,所以不知道原文地址何處,敬請(qǐng)諒解!
大致思路:
采用SqlServer方式存儲(chǔ)Session,分析數(shù)據(jù)庫表結(jié)構(gòu)、原理、流程,大致可以得到SqlServer存儲(chǔ)Session的方法:
表結(jié)構(gòu):
ASPStateTempApplications表存儲(chǔ)應(yīng)用程序Id及名稱
ASPStateTempSessions表存儲(chǔ)具體的Session值
不同的應(yīng)用程序會(huì)在ASPStateTempApplications中注冊(cè)不同的數(shù)據(jù),從而在ASPStateTempSessions中有不同的Session,如果要實(shí)現(xiàn)Session共享,可以用欺騙SqlServer的方法:用某種方法使得不同的應(yīng)用程序訪問數(shù)據(jù)庫時(shí)用相同的App!為了達(dá)到這個(gè)目的,分析[dbo].[TempGetAppID]這個(gè)存儲(chǔ)過程,代碼如下:
1![]() 2 ![]() 3 ![]() 4 ![]() 5 ![]() 6 ![]() 7 ![]() 8 ![]() 9 ![]() 10 ![]() 11 ![]() 12 ![]() 13 ![]() 14 ![]() 15 ![]() 16 ![]() 17 ![]() 18 ![]() 19 ![]() 20 ![]() 21 ![]() 22 ![]() 23 ![]() 24 ![]() 25 ![]() 26 ![]() 27 ![]() 28 ![]() 29 ![]() 30 ![]() 31 ![]() 32 ![]() 33 ![]() 34 ![]() 35 ![]() 36 ![]() 37 ![]() 38 ![]() 39 ![]() 40 ![]() 41 ![]() 42 ![]() 43 ![]() |
可以看到傳入?yún)?shù)是AppName,通過AppName獲取AppId,如果不存在則在ASPStateTempApplications表中插入該條記錄,這里AppName參數(shù)在傳入時(shí)是不同的應(yīng)用程序不同的,當(dāng)然我們可以在這里小改一下...注意第5行 SET @appName = LOWER(@appName) 我們可以毫不客氣的改成 SET @appName = 'Everything you want ^_^'
好了(不知道這樣做微軟會(huì)不會(huì)很不悅...),大功告成,清理殘留的Session,最好重啟一下IIS,不用修改舊程序本身絲毫(配置web.config除外),實(shí)現(xiàn)了Session共享...以后凡是使用該數(shù)據(jù)庫作為Session存儲(chǔ)的都可以共享Session了...
其他的一些配置說明如下:
配置web.config節(jié):
配置SQLServer:
修改[dbo].[TempGetAppID]:將@appName設(shè)為一個(gè)定值,修改保存。
清理Session,重啟IIS,KO!
另外:這個(gè)方法其實(shí)很Bug 嘿嘿 再多研究下數(shù)據(jù)庫的存儲(chǔ)過程或者用某種方法定制appName的話,可能可以實(shí)現(xiàn)更多的功能。
只這樣還不夠,需要將Session的Cookie寫到客戶端,可以讓多個(gè)程序進(jìn)行讀取。
今天, 我要寫的是如何在二級(jí)域名站點(diǎn)之間,主站點(diǎn)和二級(jí)域名站點(diǎn)之間共享Session。
首先, Session要共享,站點(diǎn)之間SessionID必須要一致,那怎么保證SessionID一致呢?
ASP.NET中的SessionID是存儲(chǔ)在客戶端的cookie之中鍵值為ASP.NET_SessionId用來維護(hù)瀏覽者Session對(duì)應(yīng)關(guān)系的一個(gè)字符串,要想在二級(jí)域名站點(diǎn)之間,主站點(diǎn)和二級(jí)域名站點(diǎn)共享SessionID就必須先共享,那么我們就必須先實(shí)現(xiàn)ASP.NET_SessionId這一cookie的共享。
CrossDomainCookieModule
------------------------------------------------------------------------------------------------
public class CrossDomainCookie : IHttpModule
{
private string m_RootDomain = string.Empty;
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
m_RootDomain = ConfigurationManager.AppSettings["RootDomain"];
context.EndRequest += new System.EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, System.EventArgs e)
{
HttpApplication app = sender as HttpApplication;
for (int i = 0; i < app.Context.Response.Cookies.Count; i++)
{
app.Context.Response.Cookies[i].Domain = m_RootDomain;
}
}
#endregion
}
上面的Module重設(shè)了所有cookie的domain到root domain, root domain在web.config中設(shè)置。也許有人會(huì)說這是眉毛胡子一把抓重寫了所有cookie的domain, 那他也可以判斷一下cookie的name, 如果為ASP.NET_SessionId的話才重寫。
如果主站點(diǎn)和二級(jí)域名站點(diǎn)是同一站點(diǎn),那么做到這一步,你的session就已經(jīng)共享了,因?yàn)镾ession的ID是相同的,而且Session容器也是同一個(gè)。
如果主站點(diǎn)和二級(jí)域名站點(diǎn)是兩個(gè)不同站點(diǎn),則需要進(jìn)行更多的操作了。
如果兩個(gè)站點(diǎn)是不同的服務(wù)器的話,解決方法要簡(jiǎn)單點(diǎn):
1) 使用相同的state server來存儲(chǔ)Session.
2) 在兩個(gè)站點(diǎn)的web.config設(shè)置相同的machineKey.
MachineKey的設(shè)置請(qǐng)參考http://msdn.microsoft.com/zh-cn/asp.net/w8h3skw9.aspx
3) 給兩個(gè)站點(diǎn)設(shè)置相同name
這樣做是為了確保兩個(gè)站點(diǎn)的siteID相同,siteID是site name的hash值,注意請(qǐng)不要使用默認(rèn)站點(diǎn),因?yàn)槟J(rèn)站點(diǎn)的siteID并非site name的hash.
如果兩個(gè)站點(diǎn)是在同一的服務(wù)器的話,需要對(duì)CrossDomainCookie再作一下修改,此方法也可應(yīng)用于兩個(gè)站點(diǎn)在不同服務(wù)器的情況:
1) 使用相同的state server來存儲(chǔ)Session.
2) 用反射來設(shè)置System.Web.SessionState.OutOfProcSessionStateStore的靜態(tài)字段s_uribase的值
public class CrossDomainCookie : IHttpModule
{
private string m_RootDomain = string.Empty;
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
m_RootDomain = ConfigurationManager.AppSettings["RootDomain"];
Type stateServerSessionProvider = typeof(HttpSessionState).Assembly.GetType("System.Web.SessionState.OutOfProcSessionStateStore");
FieldInfo uriField = stateServerSessionProvider.GetField("s_uribase", BindingFlags.Static | BindingFlags.NonPublic);
if (uriField == null)
throw new ArgumentException("UriField was not found");
uriField.SetValue(null, m_RootDomain);
context.EndRequest += new System.EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, System.EventArgs e)
{
HttpApplication app = sender as HttpApplication;
for (int i = 0; i < app.Context.Response.Cookies.Count; i++)
{
app.Context.Response.Cookies[i].Domain = m_RootDomain;
}
}
#endregion
}
完成這樣的修改之后就可以實(shí)現(xiàn)Session的共享了。
同樣如果你是使用SQL server來存儲(chǔ)Session, 也可以使用類似的方法來解決Session共享問題。
示例文件下載 http://files.cnblogs.com/jzywh/ShareSessionSample.zip
聯(lián)系客服