セッションの有効期限が切れたときにユーザーを自動的に (つまり、ポストバックなしで) プッシュする Web サイトの背後にある手法に関するチュートリアル、ブログ エントリ、またはヘルプを探しています。どんな助けでも大歓迎です
10 に答える
通常、セッション タイムアウトを設定し、ページ ヘッダーを追加して、現在のページを、セッション タイムアウトの直前にセッションをクリアするページに自動的にリダイレクトすることができます。
http://aspalliance.com/1621_Implementing_a_Session_Timeout_Page_in_ASPNET.2から
namespace SessionExpirePage
{
public partial class Secure : System.Web.UI.MasterPage
{
public int SessionLengthMinutes
{
get { return Session.Timeout; }
}
public string SessionExpireDestinationUrl
{
get { return "/SessionExpired.aspx"; }
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.PageHead.Controls.Add(new LiteralControl(
String.Format("<meta http-equiv='refresh' content='{0};url={1}'>",
SessionLengthMinutes*60, SessionExpireDestinationUrl)));
}
}
}
SessionExpireDestinationUrl は、セッションとその他のユーザー データを消去するページにリンクする必要があります。
更新ヘッダーの有効期限が切れると、自動的にそのページにリダイレクトされます。
Web サイトからクライアントを実際に「プッシュ」することはできません。あなたのサイトはクライアントからのリクエストに応えますが、それだけです。
これが意味することは、おそらく現在の時刻とサイトの Cookie にある最新の時刻を比較することによって、ユーザーがタイムアウトになったことを判断するクライアント側 (Javascript) を記述する必要があるということです (現在の Cookie で更新します)。ユーザーがあなたのサイトのページにアクセスするたびに)、その差が一定量を超える場合はリダイレクトします。
(一部の人々は、ページで一定時間後にユーザーを転送するスクリプトを作成することを主張していることに注意してください。これは単純なケースでは機能しますが、ユーザーがサイトで2つのウィンドウを開いており、 1 つのウィンドウは頻繁に、もう 1 つのウィンドウはそれほど多くなく、それほど多くないウィンドウは、ユーザーが常にサイトにアクセスしているにもかかわらず、突然転送ページにユーザーをリダイレクトします。サーバー側で行っている任意のセッションを維持します.一方、コーディングは確かに簡単であり、それで十分である場合は素晴らしいです!)
<HEAD> セクションで、次のように META 更新タグを使用します。
<meta http-equiv="refresh" content="0000; URL=target_page.html">
ここで、0000 は秒単位のセッション タイムアウト、target_page.html はリダイレクト先のページのアドレスです。
Custom Page クラスと Javascript を使用して、それを実現することもできます。
カスタム ページベース クラスを作成し、共通機能コードをこのクラスに書き込みます。このクラスを通じて、共通の機能を他の Web ページに共有できます。このクラスでは、System.Web.UI.Pageクラスを継承する必要があります。以下のコードを Pagebase クラスに配置します
PageBase.cs
namespace AutoRedirect
{
public class PageBase : System.Web.UI.Page
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
AutoRedirect();
}
public void AutoRedirect()
{
int int_MilliSecondsTimeOut = (this.Session.Timeout * 60000);
string str_Script = @"
<script type='text/javascript'>
intervalset = window.setInterval('Redirect()'," +
int_MilliSecondsTimeOut.ToString() + @");
function Redirect()
{
window.location.href='/login.aspx';
}
</script>";
ClientScript.RegisterClientScriptBlock(this.GetType(), "Redirect", str_Script);
}
}
}
上記のAutoRedirect 関数は、 javascript window.setIntervalを使用して、セッションが期限切れになったときにログイン ページをリダイレクトするために使用されます。この window.setInterval は、特定の時間遅延で JavaScript 関数を繰り返し実行します。ここでは、セッション タイムアウト値として遅延時間を設定しています。セッションの有効期限に達すると、自動的にリダイレクト機能が実行され、ログイン ページへの制御が転送されます。
OriginalPage.aspx.cs
namespace appStore
{
public partial class OriginalPage: Basepage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
OriginalPage.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="OriginalPage.aspx.cs" Inherits="AutoRedirect.OriginalPage" %>
Web.config
<system.web>
<sessionState mode="InProc" timeout="3"></sessionState>
</system.web>
注: Javascript を使用する利点は、location.href の前にアラート ボックスにカスタム メッセージを表示できることです。これは、ユーザーにとって完全に理にかなっています。Javascript を使用したくない場合は、メタ リダイレクトも選択できます。
public void AutoRedirect()
{
this.Header.Controls.Add(new LiteralControl(
String.Format("<meta http-equiv='refresh' content='{0};url={1}'>",
this.Session.Timeout * 60, "login.aspx")));
}
Just copy and paste this code snippet in your Web.Config file :
<authentication mode="Forms">
<forms loginUrl="~/Login.aspx" slidingExpiration="true" timeout="29" />
</authentication>
<sessionState timeout="30" mode="InProc" cookieless="false" />
You can put this line to your Site.Master :
Response.AppendHeader("Refresh",
Convert.ToString((Session.Timeout * 60)) +
";URL=~/Login.aspx");
私は初心者としてMVC3 ASP.netを使用しています。セッションの問題を解決するために多くの解決策を試しました(コードでセッション変数を使用しているため、タイムアウト後、使用し続けている間にセッション値がありませんでした。私の問題は構成ファイルにあることがわかりました.AuthenticationとsessionState間のタイムアウトは非常に近いはずです.したがって、それらは同時に強制終了(空)//テスト用にタイムアウト1と2を追加..少なくとも29である必要があり、 30
私はそれがうまくいくように他の方法を使用しました:
から始まる :
protected void Session_Start(object src, EventArgs e)
{
if (Context.Session != null)
{
if (Context.Session.IsNewSession)//|| Context.Session.Count==0)
{
string sCookieHeader = Request.Headers["Cookie"];
if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
{
//if (Request.IsAuthenticated)
FormsAuthentication.SignOut();
Response.Redirect("/Account/LogOn");
}
}
}
}
protected void Session_End(object sender, EventArgs e)
{
//Code that runs when a session ends.
//Note: The Session_End event is raised only when the sessionstate mode
//is set to InProc in the Web.config file. If session mode is set to StateServer
//or SQLServer, the event is not raised.
Session.Clear();
}
と :
public class SessionExpireFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext ctx = HttpContext.Current;
// check if session is supported
if (ctx.Session != null)
{
// check if a new session id was generated
if (ctx.Session.IsNewSession)
{
// If it says it is a new session, but an existing cookie exists, then it must
// have timed out
string sessionCookie = ctx.Request.Headers["Cookie"];
if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
{
ctx.Response.Redirect("~/Home/LogOn");
}
}
}
base.OnActionExecuting(filterContext);
}
}
さらに、Ajax と連携してセッションの問題を解決しました。
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Session.Count == 0 || Session["CouncilID"] == null)
Response.Redirect("/Account/LogOn");
if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null))
{
filterContext.RequestContext.HttpContext.Response.StatusCode = 401;
}
else
{
base.OnActionExecuting(filterContext);
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeUserAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (!httpContext.Request.IsAjaxRequest())
{//validate http request.
if (!httpContext.Request.IsAuthenticated
|| httpContext.Session["User"] == null)
{
FormsAuthentication.SignOut();
httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString());
return false;
}
}
return true;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new JsonResult
{
Data = new
{
// put whatever data you want which will be sent
// to the client
message = "sorry, but you were logged out"
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
残念ながらそれはできません。セッション タイムアウトはサーバー側でのみ発生し、ユーザーが何らかのポスト バック アクションを実行するまで、これは検出されません。
ただし、できることは、セッション タイムアウトと同じ時間枠でユーザーを自動的にログアウト ページにプッシュする HTML または JavaScript ヘッダー コードを挿入することです。これは完全な同期を保証するものではなく、ユーザーが時間のかかるアイテムを実行していて、時計をリセットしていない場合、問題が発生する可能性があります。
通常、これを実現するために、このコードを Page_Load イベントに追加します。
' Register Javascript timeout event to redirect to the login page after inactivity
Page.ClientScript.RegisterStartupScript(Me.GetType, "TimeoutScript", _
"setTimeout(""top.location.href = 'Login.aspx'""," & _
ConfigurationManager.AppSettings("SessionTimeoutMilliseconds") & ");", True)
もちろん[Authorize]
、特定のコントローラークラスまたはアクションでさえ使用する必要があります。
[Authorize]
public class MailController : Controller
{
}
また、次のログオン コントローラーを使用すると、ログオン前に要求された URL に送信されます。
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
//return Redirect(returnUrl);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Zhaph - Ben Duguid が指摘したように、これは AJAX リクエストに対しては注意が必要です。これをAJAXで機能させるための私のソリューションは次のとおりです(Telerik Webコントロールを使用しますが、ASP.NET AJAXツールキットを使用して構築されていると思います)。
一言で言えば、私は独自のスライド有効期限セッション タイプのものをロールバックしました。
私の Site.Master では、ポストバックごとにセッション変数を更新しています (ポストバックまたは AJAX リクエストは、AJAX リクエストがまだ Page_Load イベントを開始しているため):
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
if (this.Request.IsAuthenticated)
this.pnlSessionKeepAlive.Visible = true;
else
this.pnlSessionKeepAlive.Visible = false;
}
if (this.Session["SessionStartDateTime"] != null)
this.Session["SessionStartDateTime"] = DateTime.Now;
else
this.Session.Add("SessionStartDateTime", DateTime.Now);
}
次に、site.master のマークアップに、「舞台裏」で使用する ASPX ページを含む iframe を含めて、カスタム スライドの有効期限が切れているかどうかを確認します。
<asp:Panel runat="server" ID="pnlSessionKeepAlive" Visible="false">
<iframe id="frame1" runat="server" src="../SessionExpire.aspx" frameborder="0" width="0" height="0" / >
</asp:Panel>
現在、SessionExpire.aspx ページで、ページを頻繁に更新し、タイムスタンプが経過しているかどうかを確認し、経過している場合は logout.aspx ページにリダイレクトして、ユーザーを戻すログイン ページを決定します。
public partial class SessionExpire : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
/* We have to do all of this because we need to redirect to 2 different login pages. The default .NET
* implementation does not allow us to specify which page to redirect expired sessions, its a fixed value.
*/
if (this.Session["SessionStartDateTime"] != null)
{
DateTime StartTime = new DateTime();
bool IsValid = DateTime.TryParse(this.Session["SessionStartDateTime"].ToString(), out StartTime);
if (IsValid)
{
int MaxSessionTimeout = Convert.ToInt32(ConfigurationManager.AppSettings["SessionKeepAliveMins"]);
IsValid = (DateTime.Now.Subtract(StartTime).TotalMinutes < MaxSessionTimeout);
}
// either their session expired or their sliding session timeout has expired. Now log them out and redirect to the correct
// login page.
if (!IsValid)
this.Logout();
}
else
this.Logout();
// check every 60 seconds to see if the session has expired yet.
Response.AddHeader("Refresh", Convert.ToString(60));
}
private void Logout()
{
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TimeoutScript",
"setTimeout(\"top.location.href = '../Public/Logout.aspx'\",\"1000\");", true);
}
}
情報を投稿した上記の人々に感謝します。これが私の解決策につながり、他の人に役立つことを願っています.