.netで唯一のログインを実現する方法

5581 ワード

Asp.Net中的用户的复数次的标志防止方法


文章の分類:.netプログラミング
Web開発では、同じユーザが同じ時間に1回しかログインできないことを要求するシステムがあります.つまり、1人のユーザがログインしている場合、終了する前に再ログインするとエラーを報告する必要があります.
一般的な処理方法は、ユーザーがログインしたときに、そのユーザーがすでにアプリケーションに存在するかどうかを判断し、存在する場合はエラーを報告し、存在しない場合はアプリケーションに追加することです(アプリケーションはすべてのセッションで共有され、webアプリケーション全体で唯一のオブジェクトです):
C#コード
  • string strUserId = txtUser.Text;   
  •   ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList;   
  •  if (list == null)   
  •   {   
  •  list = new ArrayList();   
  •   }   
  •  for (int i = 0; i < list.Count; i++)   
  •   {   
  •  if (strUserId == (list[i] as string))   
  •   {   
  • //登録済み、エラーメッセージ
  • を提示
  •   lblError.Text=「このユーザーはすでにログインしています」   
  •  return;   
  •   }   
  •  }   
  •   list.Add(strUserId);   
  •  Application.Add("GLOBAL_USER_LIST", list);  
  •  string strUserId = txtUser.Text; 
    
      ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList; 
    
      if (list == null) 
    
      { 
    
      list = new ArrayList(); 
    
      } 
    
      for (int i = 0; i < list.Count; i++) 
    
      { 
    
      if (strUserId == (list[i] as string)) 
    
      { 
    
      //     ,       
    
      lblError.Text = "       "; 
    
      return; 
    
      } 
    
      } 
    
      list.Add(strUserId); 
    
      Application.Add("GLOBAL_USER_LIST", list);

    もちろんここはCacheなどを使って保存してもいいです.
    次に、ユーザが終了したときにこのユーザをApplicationから除去する、Global.asaxのSession_Endイベントでの処理:
    C#コード
  • void Session_End(object sender, EventArgs e)   
  •    {   
  • //セッション終了時に実行されるコード.   
  • //注意:Webのみconfigファイルのsessionstateモードは
  • に設定されています.
  • //InProcの場合、セッションが発生します.Endイベント.セッション・モードがStateServer
  • に設定されている場合
  • //またはSQLServerでは、このイベントは発生しません.   
  •    string strUserId = Session["SESSION_USER"] as string;   
  •    ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList;   
  •    if (strUserId != null && list != null)   
  •   {   
  •    list.Remove(strUserId);   
  •   Application.Add("GLOBAL_USER_LIST", list);   
  •    }   
  •   }  
  • void Session_End(object sender, EventArgs e) 
    
      { 
    
      //            。 
    
      //   :     Web.config      sessionstate       
    
      // InProc  ,     Session_End   。          StateServer 
    
      //   SQLServer,        。 
    
      string strUserId = Session["SESSION_USER"] as string; 
    
      ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList; 
    
      if (strUserId != null && list != null) 
    
      { 
    
      list.Remove(strUserId); 
    
      Application.Add("GLOBAL_USER_LIST", list); 
    
      } 
    
      }

    これらは問題ありません.問題は、ユーザーがブラウザの右上隅の閉じるボタンを直接クリックしたときに問題があることです.直接閉じると、すぐにセッションの有効期限が切れるイベントがトリガーされるわけではないので、ブラウザを閉じてからログインしてもログインできません.
    ここには2つの処理方法があります.
    1、Javascript方式を使う
    各ページにjavascriptコードを追加します.
    Jsコード
  • function window.onbeforeunload()   
  •   {   
  •  if (event.clientX>document.body.clientWidth && event.clientY<0||event.altKey){   
  •   window.open("logout.aspx");   
  •   }   
  •  }  
  •  function window.onbeforeunload() 
    
      { 
    
      if (event.clientX>document.body.clientWidth && event.clientY<0||event.altKey){ 
    
      window.open("logout.aspx"); 
    
      } 
    
      }

    onbeforeunloadメソッドはブラウザのシャットダウン、リフレッシュ、ページ転送などの場合に実行されるため、シャットダウンボタンをクリックした場合やAlt+F 4を押した場合に本格的なシャットダウン操作が実行されると判断する必要がある.
    そしてaspxのPage_Loadに書き込みとSession_Endと同じ方法で、同時にlogout.aspxにイベントを追加する:onload=“javascript:window.close()”
    しかし、javascriptはブラウザによって異なる動作をする可能性があります.また、ファイル->閉じることで判断されません.
    2、xmlhttpメソッドを使用する(この方法はテストしても問題ない)
    各ページに次のjavascriptを入れます(これらのjavascriptは共通に書くこともできますし、各ページに導入すればいいです)
    Jsコード
  • var x=0;   
  •  function myRefresh()   
  •   {   
  •  var httpRequest = new ActiveXObject("microsoft.xmlhttp");   
  •   httpRequest.open("GET", "test.aspx", false);   
  •   httpRequest.send(null);   
  •   x++;   
  • if(x<60)/60回、つまりSessionの本当の有効期限は30分
  • です.
  •   {   
  •  setTimeout("myRefresh()",30*1000);//30秒
  •  }   
  •   }   
  •  myRefresh();  
  •  var x=0; 
    
      function myRefresh() 
    
      { 
    
      var httpRequest = new ActiveXObject("microsoft.xmlhttp"); 
    
      httpRequest.open("GET", "test.aspx", false); 
    
      httpRequest.send(null); 
    
      x++; 
    
      if(x<60) //60 ,   Session        30   
    
      { 
    
      setTimeout("myRefresh()",30*1000); //30  
    
      } 
    
      } 
    
      myRefresh();

    Webでconfigでの設定
    Xmlコード
  •    
  • <sessionState mode="InProc" timeout="1"></sessionState> 

      test.aspxページは空のページですが、Page_Loadに追加:
    C#コード
  • Response.Expires = -1;  
  •  Response.Expires = -1;

    キャッシュを使用しないで、毎回このページに呼び出されることを保証します.
    原理は、セッションの有効期限を1分に設定し、各ページに30秒ごとにテストページを接続し、セッションを有効にし、合計60回、つまり30分連続で接続することです.30分後にユーザーがまだ操作していない場合、Sessionは期限切れになります.もちろん、ユーザーがブラウザを直接閉じると、1分後にSessionも期限切れになります.これで要求を満たすことができます.