asp.net mvc4开启SqlServer 会话共享模式
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
應(yīng)用部署結(jié)構(gòu)(精簡(jiǎn)):
站點(diǎn)部署在Nginx后面,以Nginx作為反向代理,不希望在Nginx上設(shè)置ip_hash,實(shí)現(xiàn)比較真實(shí)的負(fù)載均衡效果。
這時(shí)考慮到需要讓site1和site2同時(shí)共享會(huì)話信息,進(jìn)行如下的配置:
默認(rèn)情況下asp.net站點(diǎn)的會(huì)話模式是采用Inproc模式,這種模式在站點(diǎn)因IIS重啟會(huì)導(dǎo)致丟失用戶會(huì)話(已經(jīng)登陸的用戶會(huì)自動(dòng)重定向到登陸頁(yè)面),在本次實(shí)踐中使用SqlServer模式
創(chuàng)建會(huì)話數(shù)據(jù)庫(kù)(獨(dú)立于應(yīng)用):
aspnet_regsql.exe -S server_ip -E -ssadd -sstype c -d dbname更多參數(shù)可以參考命令的幫助aspnet_regsql.exe /?,通常路徑在**C:\Windows\Microsoft.NET\Framework64\{.net_version}**下
配置如下:
<sessionState mode="SQLServer" sqlConnectionString="server=server_ip;database=dbname;uid=user;pwd=pwd;" allowCustomSqlDatabase="True" cookieless="false" timeout="20" />會(huì)話數(shù)據(jù)庫(kù)的表ASPStateTempApplications中存放應(yīng)用的信息(appId和AppName),每一個(gè)站點(diǎn)一條記錄,我兩個(gè)站點(diǎn)分別使用該數(shù)據(jù)庫(kù)所以有兩條記錄,如圖:
通過(guò)以上的配置, 貌似完成了會(huì)話的共享,這時(shí)候通過(guò)Nginx的IP地址發(fā)送兩個(gè)請(qǐng)求到服務(wù)器(一個(gè)登陸,一個(gè)獲取用戶考試列表)。通過(guò)Nginx的日志發(fā)現(xiàn)兩次請(qǐng)求被分發(fā)到兩臺(tái)不同的后端服務(wù)器:
從圖中可以看出第一次請(qǐng)求是192.168.2.2:80803這個(gè)站點(diǎn)處理,第二個(gè)請(qǐng)求被192.168.2.5:8083這個(gè)站點(diǎn)處理。明明已經(jīng)設(shè)置了會(huì)話共享為什么第二次請(qǐng)求被提示為未登錄。檢查是否登陸的代碼如下:
public class WebApiCheckLoginFilterAttribute : ActionFilterAttribute{public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext){LoginService service = new LoginService();string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;string actionName = actionContext.ActionDescriptor.ActionName;bool isAuthAction = controllerName.Equals("ExamAPI") && actionName.Equals("Login");if (!isAuthAction){HttpSessionState Session = System.Web.HttpContext.Current.Session;if (Session["user"] == null){throw new HttpException((int)HttpStatusCode.NonAuthoritativeInformation, "未登錄用戶或已在其他設(shè)備中登錄");}if (!service.IsOnline(Model.DeviceType.Phone, Session.SessionID)){throw new HttpException((int)HttpStatusCode.NonAuthoritativeInformation, "未登錄用戶或已在其他設(shè)備中登錄");}}base.OnActionExecuting(actionContext);}}上述代碼是為了檢查如果session['user']==null,就會(huì)提示是未登陸。已經(jīng)配置了會(huì)話共享為什么session['user']還是獲取不到用戶對(duì)象?通過(guò)各種嘗試發(fā)現(xiàn)asp.net在處理session的時(shí)候會(huì)根據(jù)站點(diǎn)的AppId加上瀏覽器上的SessionId在數(shù)據(jù)庫(kù)表([ASPStateTempSessions])中創(chuàng)建會(huì)話記錄,SessionId的值如下:
0kf0zoq4to3h0z0b1eztw43s28d8c075- 28d8c075 是AppId685293685的16進(jìn)制(對(duì)應(yīng)的AppId)
- 0kf0zoq4to3h0z0b1eztw43s是客戶端cookie中存放的sessionid
通過(guò)查看存儲(chǔ)過(guò)程[dbo].[TempGetAppID]的代碼,發(fā)現(xiàn)asp.net會(huì)通過(guò)每個(gè)站點(diǎn)的AppName(見(jiàn)表ASPStateTempApplications)去獲取AppId,然后將SessionId+AppId(16進(jìn)制)作為主鍵插入到表ASPStateTempSessions中,這樣的處理邏輯是保證一個(gè)會(huì)話數(shù)據(jù)庫(kù)會(huì)被N個(gè)站點(diǎn)共同使用,不用每個(gè)站點(diǎn)創(chuàng)建自己的會(huì)話數(shù)據(jù)庫(kù)。隱藏的問(wèn)題是如果站點(diǎn)的AppName不一樣會(huì)導(dǎo)致獲取的AppId不一樣達(dá)不到會(huì)話共享的目的。
驗(yàn)證過(guò)程如下:向Nginx發(fā)送兩個(gè)請(qǐng)求(一個(gè)登陸,一個(gè)獲取考試列表)會(huì)在ASPStateTempSessions表中產(chǎn)生兩條記錄,正常情況應(yīng)該兩個(gè)請(qǐng)求也應(yīng)該只產(chǎn)生一條會(huì)話記錄。
為了保證只產(chǎn)生一條會(huì)話記錄可以通過(guò)讓site1和site2的AppName保持一致,每次通過(guò)存儲(chǔ)過(guò)程[dbo].[TempGetAppID]獲取的AppId都是同一個(gè)。 修改方式為:
修改完成后,再次發(fā)送兩個(gè)請(qǐng)求(一個(gè)登陸,一個(gè)獲取考試列表),兩個(gè)請(qǐng)求經(jīng)過(guò)Nginx分發(fā)到兩個(gè)站點(diǎn)后在ASPStateTempSessions只產(chǎn)生一條會(huì)話記錄,這樣才真正的實(shí)現(xiàn)會(huì)話的一致性。
配置machineKey,在做asp.net站點(diǎn)集群的時(shí)候如果站點(diǎn)中使用到cookie或viewstate的話需要配置machineKey來(lái)確保多臺(tái)機(jī)器共享驗(yàn)證和ViewState.每個(gè)節(jié)點(diǎn)上的machineKey配置必須一致
按照MSDN的標(biāo)準(zhǔn)說(shuō)法:“對(duì)密鑰進(jìn)行配置,以便將其用于對(duì) Forms 身份驗(yàn)證 Cookie 數(shù)據(jù)和視圖狀態(tài)數(shù)據(jù)進(jìn)行加密和解密,并將其用于對(duì)進(jìn)程外會(huì)話狀態(tài)標(biāo)識(shí)進(jìn)行驗(yàn)證.加密和解密使用的就是machineKey
生成machineKey的代碼
public static string CreateMachineKey(int length){byte[] random = new byte[length / 2];RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();rng.GetBytes(random);StringBuilder builder = new StringBuilder();for (int i = 0; i < random.Length; i++){builder.Append(string.Format("{0:X2}", random[i]));}return builder.ToString();}string decryptionKey= CreateMachineKey(48);string validationKey = CreateMachineKey(128);web.config配置內(nèi)容
<system.web><compilation targetFramework="4.0" /><machineKey validationKey="validationKey" decryptionKey="decryptionKey"/> ...other...</system.web>小結(jié)
asp.net 站點(diǎn)的會(huì)話模式如果選用SqlServer的話,需要保證站點(diǎn)群(可能有N個(gè)站點(diǎn))通過(guò)[dbo].[TempGetAppID]存儲(chǔ)過(guò)程獲取AppId后的結(jié)果是相同的??梢酝ㄟ^(guò)修改存儲(chǔ)過(guò)程,也可以通過(guò)修改AppName。
轉(zhuǎn)載于:https://my.oschina.net/hulingfeng/blog/1525737
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的asp.net mvc4开启SqlServer 会话共享模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: WEB开发常用软件集合
- 下一篇: android 9格式吗,Android