次の方法で共有


C#.NET を使用して ASP.NET アプリケーションにフォーム ベースの認証を実装する

この記事では、データベースを使用してユーザーを格納することで、フォーム ベースの認証を実装する方法について説明します。 これは、次の Microsoft .NET Framework クラス ライブラリ名前空間を参照します。

  • System.Data.SqlClient
  • System.Web.Security

元の製品バージョン: ASP.NET
元の KB 番号: 301240

要件

次の一覧では、必要な推奨ハードウェア、ソフトウェア、ネットワーク インフラストラクチャ、およびサービス パックの概要を示します。

  • Visual Studio .NET
  • インターネット インフォメーション サービス (IIS) バージョン 5.0 以降
  • SQL Server

C# .NET を使用して ASP.NET アプリケーションを作成する

  1. Visual Studio .NET を開きます。
  2. 新しい ASP.NET Web アプリケーションを作成し、名前と場所を指定します。

Web.config ファイルでセキュリティ設定を構成する

このセクションでは、 <authentication><authorization> 構成セクションを追加および変更して、フォーム ベースの認証を使用するように ASP.NET アプリケーションを構成する方法について説明します。

  1. ソリューション エクスプローラーで、Web.config ファイルを開きます。

  2. 認証モードを Forms に変更します。

  3. <Forms> タグを挿入し、適切な属性を入力します。 次のコードをコピーし、Edit メニューの Paste as HTML を選択して、ファイルの <authentication> セクションにコードを貼り付けます。

    <authentication mode="Forms">
        <forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx"
            protection="All" path="/" timeout="30" />
    </authentication>
    
  4. 次のように、 <authorization> セクションで匿名ユーザーへのアクセスを拒否します。

    <authorization>
        <deny users ="?" />
        <allow users = "*" />
    </authorization>
    

ユーザーの詳細を格納するサンプル データベース テーブルを作成する

このセクションでは、ユーザーのユーザー名、パスワード、ロールを格納するサンプル データベースを作成する方法について説明します。 ユーザー ロールをデータベースに格納し、ロールベースのセキュリティを実装する場合は、ロール列が必要です。

  1. Start メニューの Run を選択し、メモ帳を入力してメモ帳を開きます。

  2. 次の SQL スクリプト コードを強調表示し、コードを右クリックし、 Copy を選択します。 メモ帳で、Edit メニューの Paste を選択して、次のコードを貼り付けます。

    if exists (select * from sysobjects where id =
    object_id(N'[dbo].[Users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
        drop table [dbo].[Users]
    GO
    CREATE TABLE [dbo].[Users] ([uname] [varchar] (15) NOT NULL,
        [Pwd] [varchar] (25) NOT NULL,
        [userRole] [varchar] (25) NOT NULL,
    ) ON [PRIMARY]
    GO
    ALTER TABLE [dbo].[Users] WITH NOCHECK ADD
        CONSTRAINT [PK_Users] PRIMARY KEY NONCLUSTERED
        ([uname]
        ) ON [PRIMARY]
    GO
    
    INSERT INTO Users values('user1','user1','Manager')
    INSERT INTO Users values('user2','user2','Admin')
    INSERT INTO Users values('user3','user3','User')
    GO
    
  3. ファイルを Users.sqlとして保存します。

  4. SQL Server コンピューターで、Query Analyzer で Users.sql を開きます。 データベースの一覧から pubs を選択し、スクリプトを実行します。 この操作により、サンプル ユーザー テーブルが作成され、このサンプル アプリケーションで使用される Pubs データベースにテーブルが設定されます。

Logon.aspx ページを作成する

  1. Logon.aspxという名前のプロジェクトに新しい Web フォームを追加します。

  2. エディターで Logon.aspx ページを開き、HTML ビューに切り替えます。

  3. 次のコードをコピーし、Edit メニューの Paste as HTML オプションを使用して、<form> タグ間にコードを挿入します。

    <h3>
        <font face="Verdana">Logon Page</font>
    </h3>
    <table>
        <tr>
            <td>Email:</td>
            <td><input id="txtUserName" type="text" runat="server"></td>
            <td><ASP:RequiredFieldValidator ControlToValidate="txtUserName"
                Display="Static" ErrorMessage="*" runat="server" 
                ID="vUserName" /></td>
        </tr>
        <tr>
            <td>Password:</td>
            <td><input id="txtUserPass" type="password" runat="server"></td>
            <td><ASP:RequiredFieldValidator ControlToValidate="txtUserPass"
            Display="Static" ErrorMessage="*" runat="server"
            ID="vUserPass" />
            </td>
        </tr>
        <tr>
            <td>Persistent Cookie:</td>
            <td><ASP:CheckBox id="chkPersistCookie" runat="server" autopostback="false" /></td>
            <td></td>
        </tr>
    </table>
    <input type="submit" Value="Logon" runat="server" ID="cmdLogin"><p></p>
    <asp:Label id="lblMsg" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat="server" />
    

    この Web フォームは、ユーザーにログオン フォームを表示するために使用され、ユーザー名とパスワードを指定してアプリケーションにログオンできるようにします。

    詳細については、「 RequiredFieldValidator クラスを参照してください。

  4. デザイン ビューに切り替えて、ページを保存します。

ユーザー資格情報を検証するようにイベント ハンドラーをコーディングする

このセクションでは、分離コード ページ (Logon.aspx.cs) に配置されるコードについて説明します。

  1. LogonをダブルクリックしてLogon.aspx.csファイルを開きます。

  2. 分離コード ファイルに必要な名前空間をインポートします。

    using System.Data.SqlClient;
    using System.Web.Security;
    
  3. データベースを調べることでユーザー資格情報を検証する ValidateUser 関数を作成します。 データベースを指す Connection 文字列を必ず変更してください。

    private bool ValidateUser( string userName, string passWord )
    {
        SqlConnection conn;
        SqlCommand cmd;
        string lookupPassword = null;
    
        // Check for invalid userName.
        // userName must not be null and must be between 1 and 15 characters.
        if ( ( null == userName ) || ( 0 == userName.Length ) || ( userName.Length > 15 ))
        {
            System.Diagnostics.Trace.WriteLine( "[ValidateUser] Input validation of userName failed." );
            return false;
        }
    
        // Check for invalid passWord.
        // passWord must not be null and must be between 1 and 25 characters.
        if ( ( null == passWord ) || ( 0 == passWord.Length ) || ( passWord.Length > 25 ))
        {
            System.Diagnostics.Trace.WriteLine( "[ValidateUser] Input validation of passWord failed." );
            return false;
        }
    
        try
        {
            // Consult with your SQL Server administrator for an appropriate connection
            // string to use to connect to your local SQL Server.
            conn = new SqlConnection( "server=localhost;Integrated Security=SSPI;database=pubs" );
            conn.Open();
    
            // Create SqlCommand to select pwd field from users table given supplied userName.
            cmd = new SqlCommand( "Select pwd from users where uname=@userName", conn );
            cmd.Parameters.Add( "@userName", SqlDbType.VarChar, 25 );
            cmd.Parameters["@userName"].Value = userName;
    
            // Execute command and fetch pwd field into lookupPassword string.
            lookupPassword = (string) cmd.ExecuteScalar();
    
            // Cleanup command and connection objects.
            cmd.Dispose();
            conn.Dispose();
        }
        catch ( Exception ex )
        {
            // Add error handling here for debugging.
            // This error message should not be sent back to the caller.
            System.Diagnostics.Trace.WriteLine( "[ValidateUser] Exception " + ex.Message );
        }
    
        // If no password found, return false.
        if ( null == lookupPassword )
        {
            // You could write failed login attempts here to event log for additional security.
            return false;
        }
    
        // Compare lookupPassword and input passWord, using a case-sensitive comparison.
        return ( 0 == string.Compare( lookupPassword, passWord, false ));
    }
    
  4. 2 つの方法のいずれかを使用して、フォーム認証 Cookie を生成し、ユーザーを cmdLogin_ServerClick イベント内の適切なページにリダイレクトできます。 サンプル コードは、両方のシナリオで提供されています。 要件に従って、いずれかを使用します。

    • RedirectFromLoginPageメソッドを呼び出してフォーム認証 Cookie を自動的に生成し、cmdLogin_ServerClick イベントの適切なページにユーザーをリダイレクトします。

      private void cmdLogin_ServerClick(object sender, System.EventArgs e)
      {
          if (ValidateUser(txtUserName.Value,txtUserPass.Value))
              FormsAuthentication.RedirectFromLoginPage(txtUserName.Value, chkPersistCookie.Checked);
          else
              Response.Redirect("logon.aspx", true);
      }
      
    • 認証チケットを生成し、暗号化し、Cookie を作成し、応答に追加して、ユーザーをリダイレクトします。 この操作により、Cookie の作成方法をより詳細に制御できます。 この場合、カスタム データを FormsAuthenticationTicket と共に含めることもできます。

      private void cmdLogin_ServerClick(object sender, System.EventArgs e)
      {
          if (ValidateUser(txtUserName.Value,txtUserPass.Value))
          {
              FormsAuthenticationTicket tkt;
              string cookiestr;
              HttpCookie ck;
              tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
              DateTime.Now.AddMinutes(30), chkPersistCookie.Checked, "your custom data");
              cookiestr = FormsAuthentication.Encrypt(tkt);
              ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
              if (chkPersistCookie.Checked)
                  ck.Expires=tkt.Expiration;
              ck.Path = FormsAuthentication.FormsCookiePath;
              Response.Cookies.Add(ck);
      
              string strRedirect;
              strRedirect = Request["ReturnUrl"];
              if (strRedirect==null)
                  strRedirect = "default.aspx";
              Response.Redirect(strRedirect, true);
          }
          else
              Response.Redirect("logon.aspx", true);
      }
      
  5. Web フォーム デザイナーによって生成されるコードの InitializeComponent メソッドに次のコードが追加されていることを確認します。

    this.cmdLogin.ServerClick += new System.EventHandler(this.cmdLogin_ServerClick);
    

Default.aspx ページを作成する

このセクションでは、認証後にユーザーがリダイレクトされるテスト ページを作成します。 ユーザーがアプリケーションに最初にログオンせずにこのページを参照すると、ログオン ページにリダイレクトされます。

  1. 既存の WebForm1.aspx ページの名前を Default.aspxに変更し、エディターで開きます。

  2. HTML ビューに切り替え、 <form> タグ間で次のコードをコピーします。

    <input type="submit" Value="SignOut" runat="server" id="cmdSignOut">
    

    このボタンは、フォーム認証セッションからログオフするために使用されます。

  3. デザイン ビューに切り替えて、ページを保存します。

  4. 分離コード ファイルに必要な名前空間をインポートします。

    using System.Web.Security;
    
  5. SignOut をダブルクリックして分離コード ページ (Default.aspx.cs) を開き、cmdSignOut_ServerClick イベント ハンドラーで次のコードをコピーします。

    private void cmdSignOut_ServerClick(object sender, System.EventArgs e)
    {
        FormsAuthentication.SignOut();
        Response.Redirect("logon.aspx", true);
    }
    
  6. Web フォーム デザイナーによって生成されるコードの InitializeComponent メソッドに次のコードが追加されていることを確認します。

    this.cmdSignOut.ServerClick += new System.EventHandler(this.cmdSignOut_ServerClick);
    
  7. プロジェクトを保存してコンパイルします。 これで、アプリケーションを使用できるようになりました。

追加メモ

  • パスワードをデータベースに安全に格納したい場合があります。 HashPasswordForStoringInConfigFileという名前の FormsAuthentication クラス ユーティリティ関数を使用して、データベースまたは構成ファイルにパスワードを格納する前にパスワードを暗号化できます。

  • 必要に応じて簡単に変更できるように、構成ファイル (Web.config) に SQL 接続情報を格納できます。

  • 異なる組み合わせのパスワードを使用しようとするハッカーがログオンするのを防ぐために、コードを追加することを検討してください。 たとえば、2 回または 3 回のログオン試行のみを受け入れるロジックを含めることができます。 一部の試行でユーザーがログオンできない場合は、別のページにアクセスするか、サポートラインを呼び出して、ユーザーがアカウントを再度有効にするまでログオンできないように、データベースにフラグを設定できます。 また、必要に応じて適切なエラー処理を追加する必要があります。

  • ユーザーは認証 Cookie に基づいて識別されるため、このアプリケーションで Secure Sockets Layer (SSL) を使用して、送信される認証 Cookie やその他の重要な情報を誰も利用できないようにすることができます。

  • フォーム ベースの認証では、クライアントがブラウザーで Cookie を受け入れるか有効にする必要があります。

  • <authentication>構成セクションのタイムアウト パラメーターは、認証 Cookie を再生成する間隔を制御します。 より優れたパフォーマンスとセキュリティを提供する値を選択できます。

  • インターネット上の特定の中継プロキシとキャッシュは、 Set-Cookie ヘッダーを含む Web サーバー応答をキャッシュし、別のユーザーに返される場合があります。 フォーム ベースの認証では Cookie を使用してユーザーを認証するため、この動作により、最初は意図されていなかった中間プロキシまたはキャッシュから Cookie を受け取ることで、ユーザーが誤って (または意図的に) 別のユーザーを偽装する可能性があります。

関連情報