PDA

View Full Version : بعد از Expire شدن session با هر درخواست session_start فراخوانی می شه



ali_mnkt
پنج شنبه 16 دی 1389, 21:41 عصر
با سلام

همون طور که همه شما اساتید می دونید زمانی که یک درخواست از یک browser به برنامه وب که روی یک سرور قرار داره می ره یک session در سرور ذخیره می شه و در browser درخواست کننده هم یک cookie که حاوی sessionId همون session ساخته شده است در browser درخواست کننده ایجاد می شه و از این به بعد اگر browser درخواستی رو به سرور بده شناخته شده است این مقدمه رو گفتم تا برم سر اصل مطلب :

در global.asax هم یک متد به نام session_start وجود داره که در دوحالت rise می شه

1- زمانی که یک browser درخواستی رو به برنامه بده و برنامه هیچ session شناسائی برای اون browser پیدا نکنه

2- session شناسائی پیدا بشه ولی Expire شده باشه

خوب حالا مشگل اینجاست که اگر session ، زمانش Expire شده باشه به ازای هر Request متد session_start شروع به اجرا می کنه که این برای برنامه هایی که قسمت آمار سایت داشته باشند خیلی بده چون بعد از Expire شدن Session یک کاربر به ازای هر reaquest اون یک واحد به بازدید کنندگان سایت اضافه می کنه

یک راه حل این مشگل اینه که در web.config درقسمت sessionState زمان timeout رو زیاد کنیم اما روش خوبی نیست چون دوباره اون زمان هم Expire می شه و روز از نو و روزی از نو.

آیا کسی راه حلی برای این مشگل داره ؟

prankster
پنج شنبه 16 دی 1389, 22:54 عصر
session کاربر زمانی تمام خواهد شد که کاربر به اندازه timeout تنظیم شده در config هیچ کنشی با برنامه نداشته باشد، عملا هنگامی که کاربر برای مدت طولانی با برنامه ارتباطی نداشته باشد و session در این مدت expire شده باشد، واقعا پس از درخواست جدید باید کاربر جدید درنظر گرفته شود، مثل اینکه مثلا چندین بار در روز به یک وبسایت مثلا برای چک کردن email سر بزنید!
مساله ای که گاها در web application ها پیش می آید این است که تا هنگام باز بودن browser کاربر (که ممکن است چندین ساعت هم طول بکشد) session کاربر timeout نشود، و تنها هنگامی که کاربر browser خود را بسته باشد کاربر جدید به حساب بیاید. دو روش برای این کار وجود دارد:
روش اول ایجاد cookie در browser کار بر است که با بستن browser از بین می رود. مثلا در صورت expire شدن session و با درخواست جدید هنگامی که session_start در برنامه raise می شود در صورت وجود cookie، از دید برنامه کاربر، یک کاربر جدید به حساب نمی آید.
روش دوم استفاده از XHR در background است، روشی که مثلا وبسایتی مثل facebook از آن استفاده می کند. در این روش یک XMLHttpRequest Object در background و به صورت asynchronous در فواصل زمانی کم درخواستی (شبیه ping) به سرور ارسال می کند، این درخواست ها مانع از expire شدن session می شود و از دید برنامه کاربر کماکان یک کاربر فعال است

ali_mnkt
پنج شنبه 16 دی 1389, 23:55 عصر
مرسی دوست عزیز از راهنماییت اما یک مشگل که اینجا وجود داره اینه که بعد از Expire شدن Session شناسائی کاربر به ازای هر request متد session_start از فایل global.asax فراخوانی و یا به قولی rise می شه . به این مطلب از msdn توجه کن


The Session_OnStart subroutine is run at the beginning of a request if the request begins a new session. A new session will be started if a request is made that does not contain a SessionID (http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid .aspx) value or if the SessionID (http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid .aspx) property contained in the request references a session that has expired

اینم آدرس منبع : http://msdn.microsoft.com/en-us/library/ms178583.aspx

خوب در این توضیح آمده که یک متد session_start زمانی اجرا می شه که یک new session شروع شود و زمانی هم یک new session ایجاد می شود که یا اصلا session ی با این مشخصات نباشه و یا session قبلی Expire شده باشه. که مشگل سر حالت دوم است یعنی زمانی که session زمانش Expire شه و هی مدام متد session_start فراخوانی شه. حالا چطور می شه جلوی این حالت رو گرفت یعنی وقتی session زمانش Expire می شه اون session رو پاک کرد تا از نو یک session جدید ساخته شه که دیگه به این مشگل بر نخوریم ؟

prankster
جمعه 17 دی 1389, 11:01 صبح
بعد از expire شدن session کاربر، با اولین درخواست، کاربر هیچ تفاوتی با یک کاربر جدید نخواهد داشت. به این معنی که asp engine برای browser کاربر sessoin ID جدید می فرستد، session_start دوباره raise می شود و از نقطه به بعد کاربر از دید سیستم واقعا کاربر جدید است. دو نکته در اینجا وجود دارد:
اول اینکه session کاربر پس از سپری شدن زمان ثابت expiration تمام نمی شود، بلکه زمانی expire می شود که از آخرین تماس browser کاربر با سرور زمانی به اندازه expiration time بگذرد
دوم، پس از expire شدن session کاربر، با اولین درخواست session جدید ایجاد می شود و تنها یک بار session_start اجرا می شود، اینگونه نیست که پس ازexpire شدن session، مرتب session_start فراخوانی بشود
در بعضی از موارد به هیچ وجه نمی خواهند که session کاربر تا زمان باز بودن browser به اتمام برسد، که در این حالت از یکی از دو روشی که قبلا گفتم استفاده می شود

ali_mnkt
جمعه 17 دی 1389, 11:51 صبح
بعد از expire شدن session کاربر، با اولین درخواست، کاربر هیچ تفاوتی با یک کاربر جدید نخواهد داشت. به این معنی که asp engine برای browser کاربر sessoin ID جدید می فرستد، session_start دوباره raise می شود و از نقطه به بعد کاربر از دید سیستم واقعا کاربر جدید است. دو نکته در اینجا وجود دارد:
اول اینکه session کاربر پس از سپری شدن زمان ثابت expiration تمام نمی شود، بلکه زمانی expire می شود که از آخرین تماس browser کاربر با سرور زمانی به اندازه expiration time بگذرد
دوم، پس از expire شدن session کاربر، با اولین درخواست session جدید ایجاد می شود و تنها یک بار session_start اجرا می شود، اینگونه نیست که پس ازexpire شدن session، مرتب session_start فراخوانی بشود
در بعضی از موارد به هیچ وجه نمی خواهند که session کاربر تا زمان باز بودن browser به اتمام برسد، که در این حالت از یکی از دو روشی که قبلا گفتم استفاده می شود

با سلام مجدد . این گفته شما که می گید بعد از Expire شدن session فقط یک بار session_start اجرا می شه و تا زمان Expire شدن session جدید دیگه اجرا نمی شه غلطه چون من زمان Timeout مربوط به sessionState رو برابر با 1 گذاشتم که معنیش اینه که هر 1 دقیقه session ها رو Expire کن و در نتیجه دیدم که بعد از Expire شدن به اضای هر request یک بار session_start فراخوانی می شه !!!!!!!!! برای این که مطمئن بشی می تونی یک امتحان ساده بکنی.

prankster
جمعه 17 دی 1389, 12:37 عصر
این مساله تنها زمانی اتفاق می افتد که session را اتفاقی abandon کرده و ASP.NET_SessionId را overwrite کنید:

Session.Abandon();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));در غیر این صورت، پس از سپری شدن زمان timeout با درخواست جدید تنها "یک بار" session_start در برنامه raise می شود.
توضیح کامل در MSDN:
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstatemodule.start.a spx
http://msdn.microsoft.com/en-us/library/ms178581.aspx
http://support.microsoft.com/kb/899918

ali_mnkt
جمعه 17 دی 1389, 15:23 عصر
دوست عزیز یک برنامه ساده برای تست ضمیمه کردم که روند کار رو نشون بدم:

این برنامه فقط شامل یک دکمه هست و یک فایل global.asax . من در web.config در sessionState زمان timeout رو 1 قراردادم در متد session_start هم یک breakpoint گذاشتم تا هر وقت rise شد مشخص شه.
خوب وقتی که برنامه رو برای اولین بار اجرا می کنیم مصلما برای اولین بار متد rise می شه بعد از اون زیر یک دقیقه هر چقدر دکمه رو بزنیم متد rise نمی شه . حالا یکم صبر کن تا 1 دقیقه تموم شه حالا دکمه رو بزن می بینی که به ازای هر کلیک متد session_start اجرا می شه و این این رو نشون می ده که وقتی session زمانش Expire شد با درخواست های متعدد هی session جدید ایجاد می کنه و نه این که یک session جدید ایجادکنه و در دفعه های بعد قبل از Expire شدن از اون استفاده کنه

prankster
جمعه 17 دی 1389, 16:26 عصر
با سلام
با اجرای برنامه ضمیمه دقیقا همان اتفاقی که شما گفتید می افتد، من برنامه را در IIS 6 و در Visual Studio 2010 هم تست کردم که نتیجه مشابهی دارد! اما با convert کردن برنامه به Net. 4 این مشکل بوجود نمی آید!
نکته جالب اینجاست که اگر چیزی (هر گونه متغیری) در session ذخیره کنید به هیچ وجه به این مشکل برخورد نمی کنید و session_start فقط یک بار اتفاق می افتد
به نظر می رسد این مشکل یک bug در Net. کمتر از 4 و زمانی که session خالی است، است.
در هر حال نکته جالی بود، ممنون:چشمک: