2011-02-03 8 views
0

LoginPage.aspx: -カスタム認証モジュール継承のIHttpModule問題

protected void Button1_Click(object sender, EventArgs e) 
      { 
       Context.Items["Username"] = txtUserId.Text; 
       Context.Items["Password"] = txtPassword.Text; 
       // 
       FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, Context.Items["Username"].ToString(), DateTime.Now, DateTime.Now.AddMinutes(10), true, "users", FormsAuthentication.FormsCookiePath); 

       // Encrypt the cookie using the machine key for secure transport 
       string hash = FormsAuthentication.Encrypt(ticket); 
       HttpCookie cookie = new HttpCookie(
        FormsAuthentication.FormsCookieName, // Name of auth cookie 
        hash); // Hashed ticket 

       // Set the cookie's expiration time to the tickets expiration time 
       if (ticket.IsPersistent) cookie.Expires = ticket.Expiration; 
       Response.Cookies.Add(cookie); 
       Response.Redirect("Default.aspx"); 
      } 

Global.asaxファイル: -

void Application_AuthenticateRequest(object sender, EventArgs e) 
     { 
      if (HttpContext.Current.User != null) 
      { 
       if (HttpContext.Current.User.Identity.IsAuthenticated) 
       { 
        if (HttpContext.Current.User.Identity is FormsIdentity) 
        { 
         FormsIdentity id = 
          (FormsIdentity)HttpContext.Current.User.Identity; 
         FormsAuthenticationTicket ticket = id.Ticket; 
         // Get the stored user-data, in this case, our roles 
         string userData = ticket.UserData; 
         string[] roles = userData.Split(','); 
         HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(id, roles); 
         Response.Write(HttpContext.Current.User.Identity.Name); 
         Response.Redirect("Default.aspx"); 
        } 
       } 
      } 
     } 

私はそこ

This webpage has a redirect loop. 

The webpage at http://localhost:1067/Default.aspx has resulted in too many redirects. Clearing your cookies for this site or allowing third-party cookies may fix the problem. If not, it is possibly a server configuration issue and not a problem with your computer. 
+0

なぜリダイレクトエラーが発生しますか? –

+0

'Application_AuthenticateRequest'はすべての*リクエスト*で起動します。ログインすると、期待通りにDefault.aspxに送られます。ただし、そのページがレンダリングされる前に、このコードが呼び出され、ブラウザがDefault.aspxにリダイレクトされます。しかし、もう一度このコードをレンダリングする前に、もう一度ブラウザをDefault.aspxにリダイレクトします。このプロセスは何かが無限のリダイレクトを検出するまで(あなたが運が良ければ)繰り返されます。 –

+0

また、投稿全体を変更しないでください。変更を加えて修正することはできますが、IHttpModuleからglobal.asaxイベントを使用するように切り替えました。これらは別々です。別の方向に進む場合は、新しい質問を作成し、該当する場合は古いものを参照してください。 –

答えて

2

これはあなたのモジュールがどのように見えるかという大まかなアイデアです。あなたのモジュールはリクエストごとにで実行されます。あなたはそれを起動したり何かを渡したりすることはありません。ASP.Netが処理するように要求されたときに自動的に起動します。

あなたのモジュールは、1)ログインページでユーザーを認証する、2)後続のページでユーザーを認証する、の2つのことを行います。最初のステップは、BeginRequestメソッドにサブスクライブすることです。このメソッドには、現在のHttpApplicationが最初のパラメータとして与えられます。そこから、ユーザーがログインページにいるかどうかを判断する必要があります。ログインページに表示されていない場合は、セッションまたはCookieまたはクエーストーントークン、またはそれらが有効かどうかを確認するために使用しているものを確認してください。無効な場合は、ログインページに戻してください。

ログインページの[]と[]がPOSTした場合は、生のフォームフィールドを確認して確認します。テキストボックス、チェックボックスなどはここには存在しません。生のフォームフィールドのみです。有効な場合は、必要に応じて(セッション、Cookieなど)認証トークンを設定します。それらが無効な場合は、ログインページにリダイレクトするか、「もう一度やり直してください」というメッセージを入力してください。

また、メッセージをダブルポストするとreference itとなりますので、すでに述べた内容のチェーンをたどることができます。

class MyModule : IHttpModule 
{ 

    void IHttpModule.Init(HttpApplication context) 
    { 
     //Subscribe to the BeginRequest event 
     context.BeginRequest += new EventHandler(this.Application_BeginRequest); 
    } 
    private void Application_BeginRequest(Object source, EventArgs e) 
    { 
     //Initialize our variables, null checks should be put here, too 
     HttpApplication app = (HttpApplication)source; 
     HttpContext context = app.Context; 
     System.Web.SessionState.HttpSessionState s = context.Session; 

     //Normally our module needs to validate every request to make sure our request is still authenticated. 
     //The exception to that rule is on our logon page where they obviously don't have credentials yet. 
     if(!context.Request.FilePath.ToLowerInvariant().StartsWith("/login.aspx")){ 
      //If we're here then we're not on the logon page, validate our current session according to whatever logic we want 
      if (s != null && s["isvalid"] == "true"){ 
       return; 
      }else{ 
       context.Response.Redirect("/login.aspx"); 
      } 
     }else{ 
      //If we're here then we're on the login page itself. If there's a post, assume that they've hit the login button 
      if (context.Request.HttpMethod == "POST") 
      { 
       //Whatever your form variables are called 
       string username = context.Request.Form["username"]; 
       string password = context.Request.Form["password"]; 
       //Your own validation logic would go here 
       if (MyCustomLogin.IsUserValid(username, password)) 
       { 
        s["isvalid"] = "true"; 
        context.Response.Redirect("/Home.aspx");  
       }else{ 
        s["isvalid"] = "false"; 
        context.Response.Redirect("/login.aspx?error=invalid_login"); 
       } 
      }else{ 
       //If we're here then the request is probably a GET or HEAD which would be from a person 
       //initially browsing to our page so just do nothing and pass it through normally 
      } 
     } 
    } 
} 
+0

素晴らしいサンプルコード!しかし、セッションは常にnullだったので、BeginRequestの代わりにPreRequestHandlerExecuteイベントを使用しなければなりませんでした... –

0

に署名した後、次のエラーを取得しますモジュール内のこの情報に直接アクセスする方法はありません(認証されたユーザーの場合は、コンテキストを介してユーザー名にアクセスできますがパスワードではありません)。モジュールは、要求に必要な認証情報が含まれているかどうかをチェックし、それに基づいて要求を処理または拒否します。あなたが故意にログインページからこの情報を収集し、モジュールのどこにアクセスできるか、例えばセッションに格納しない限り。しかし理想的には、パスワードを保存することは広く推奨されていません。認証に使用して破棄してください。

モジュール内でこの情報にアクセスしたいという理由から、理想的にはもっと光を放つことができます。

編集は、チャンダンのコメントの後:

@Chandan、ここにあなたのコメントは何がやりたいことは、標準的なフォーム認証を使用して反対としてあなた認証にHttpModuleをを使用している私に示唆しています。私が軌道に乗っているなら、codeprojectでこのプロジェクトをhttp://www.codeproject.com/KB/web-security/AspNetCustomAuth.aspxにチェックすることができます。 Goodluck

+0

まあ、いくつかの記事はカスタム認証について言及していますが、テキストボックスからデータを取り込むのではなく、urlで渡された変数からパラメータとして取ります。このシナリオを考えると、authenticaterequestは本当に多くのことを行うことができません。モジュールレベルでの処理に役立つリクエストレベルのイベントの良い例を教えてください。 –