ASP.NET Web ページ (Razor) サイトへのセキュリティとメンバーシップの追加

作成者: Tom FitzMacken

この記事では、一部のページがログインしたユーザーのみに使用可能になるように、ASP.NET Web ページ (Razor) Web サイトをセキュリティで保護する方法について説明します。 (誰でもアクセスできるページを作成する方法も説明します)。

学習内容:

  • 一部のページについてアクセスをメンバーのみに制限できるように、登録ページとログイン ページを含む Web サイトを作成する方法。
  • パブリック ページとメンバー専用ページを作成する方法。
  • ロール (サイトで異なるセキュリティ アクセス許可を持つグループ) を定義する方法と、ロールにユーザーを割り当てる方法。
  • CAPTCHA を使用して、自動プログラム (ボット) がメンバー アカウントを作成できないようにする方法。

この記事で紹介する ASP.NET 機能は次のとおりです。

  • WebMatrix のスターター サイト テンプレート。
  • WebSecurity ヘルパーと Roles クラス。
  • ReCaptcha ヘルパー。

チュートリアルで使用するソフトウェアのバージョン

  • ASP.NET Web ページ (Razor) 2
  • WebMatrix 3
  • ASP.NET Web ヘルパー ライブラリ

ユーザーが Web サイトにログインできるように、つまりサイトが "メンバーシップ" をサポートするように Web サイトをセットアップできます。 これは、多くの理由で便利です。 たとえば、サイトに、メンバーのみに使用可能になるようにするページが存在する場合があります。 ユーザーがフィードバックを送信したり、コメントを残したりする場合に、ログインを必須にすることもあります。

Web サイトがメンバーシップをサポートしている場合でも、サイト上のページの一部をユーザーが使用する前にログインする必要があるとは限りません。 ログインしていないユーザーは "匿名ユーザー" と呼ばれます。

ユーザーは Web サイトに登録でき、次にサイトにログインできます。 Web サイトは、ユーザーが本人であることを確認するために、ユーザー名 (メール アドレス) とパスワードを必要とします。 ログインしてユーザーの ID を確認するこのプロセスは、"認証" と呼ばれます。

セキュリティとメンバーシップは、次のようにさまざまな方法でセットアップできます。

  • WebMatrix を使用する場合、スターター サイト テンプレートに基づいて新しいサイトとして作成する方法が簡単です。 このテンプレートは、セキュリティとメンバーシップ用に既に構成されていて、登録ページ、ログイン ページなどが既にあります。

    テンプレートによって作成されるサイトには、ユーザーが Facebook、Google、Twitter などの外部サイトを使用してログインできるようにするオプションもあります。

  • 既存のサイトにセキュリティを追加する場合や、スターター サイト テンプレートを使用しない場合は、独自の登録ページやログイン ページなどを作成できます。

この記事では、1 番めのオプションである、スターター サイト テンプレートを使用してセキュリティを追加する方法について説明します。 独自のセキュリティを実装する方法に関する基本的な情報と、その方法に関する詳細情報へのリンクも提供します。 外部ログインを有効にする方法に関する情報もあります。この詳細については、別の記事で説明します。

スターター サイト テンプレートを使用して Web サイト セキュリティを作成する

WebMatrix では、スターター サイト テンプレートを使用して、次を含む Web サイトを作成できます。

  • メンバーのユーザー名とパスワードを格納するために使用されるデータベース。
  • 匿名 (新規) ユーザーが登録できる登録ページ。
  • ログインとログアウトのページ。
  • パスワードの回復とリセットのページ。

サイトを作成して構成する方法について、次の手順で説明します。

  1. WebMatrix を起動し、[クイック スタート] ページで [Site From Template] (テンプレートからサイト) を選択します。

  2. スタート サイト テンプレートを選択し、[OK] をクリックします。 WebMatrix が新しいサイトを作成します。

  3. 左側のウィンドウで、[ファイル] ワークスペース セレクターをクリックします。

  4. Web サイトのルート フォルダーで、_AppStart.cshtml ファイルを開きます。これは、グローバル設定を含めるために使用される特殊なファイルです。 これには、// 文字を使用してコメント アウトされているステートメントがいくつか含まれています。

    //WebMail.SmtpServer = "mailserver.example.com";
    //WebMail.EnableSsl = true;
    //WebMail.UserName = "username@example.com";
    //WebMail.Password = "your-password";
    //WebMail.From = "your-name-here@example.com";
    

    これらのステートメントは、メールの送信に使用できる WebMail ヘルパーを構成します。 メンバーシップ システムは、ユーザーが登録するときや、パスワードを変更するときに、メールを使用して確認メッセージを送信できます。 (たとえば、ユーザーは、登録後に、登録プロセスを完了するためにクリックできるリンクを含むメールを受け取ります)。

    メールを送信するには、ASP.NET Web ページ サイトへのメールの追加に関する記事の説明どおり、SMTP サーバーへのアクセス権が必要です。 メールを送信できる各ページに繰り返しコーディングせずに済むように、この中央の _AppStart.cshtml ファイルにメール設定を格納します。 (登録データベースをセットアップするために SMTP 設定を構成する必要はありません。SMTP 設定は、ユーザーのメール エイリアスからユーザーを検証して、忘れたパスワードをユーザーがリセットできるようにする場合にのみ必要です)。

  5. 各ステートメントの前から // を削除して、ステートメントのコメントを解除します。

    メールの確認をセットアップしない場合は、この手順と次の手順をスキップできます。 SMTP 値が設定されていない場合、新しいアカウントは確認メールなしですぐに使用できます。

  6. コードでメール関連の次の設定を変更します。

    • WebMail.SmtpServer をアクセス権を持つ SMTP サーバーの名前に設定します。

    • WebMail.EnableSsltrue に設定したままにします。 この設定は、SMTP サーバーに送信される資格情報を暗号化してセキュリティで保護します。

    • WebMail.UserName を SMTP サーバー アカウントのユーザー名に設定します。

    • WebMail.Password を SMTP サーバー アカウントのパスワードに設定します。

    • WebMail.From を自分のメール アドレスに設定します。 これは、メッセージの送信元のメール アドレスです。

      Note

      ヒント これらのプロパティの値の詳細については、「ASP.NET Web ページのサイト全体の動作をカスタマイズする」のメール設定の構成に関する記事を参照してください。

  7. _AppStart.cshtml を保存して閉じます。

  8. ブラウザーで Default.cshtml ページを実行します。

    security-membership-2

    Note

    プロパティが ExtendedMembershipProvider のインスタンスであることが必要であることを示すエラーが表示された場合は、ASP.NET Web ページのメンバーシップ システム (SimpleMembership) を使用するようにサイトが構成されていない可能性があります。 これは、ホスティング プロバイダーのサーバーがローカル サーバーとは異なる方法で構成されている場合に発生することがあります。 これを修正するには、サイトの Web.config ファイルに次の要素を追加します。

    <appSettings>
        <add key="enableSimpleMembership" value="true" />
    </appSettings>
    

    この要素を <configuration> 要素の子、かつ <system.web> 要素のピアとして追加します。

  9. ページの右上隅にある [登録] リンクをクリックします。 Register.cshtml ページが表示されます。

  10. ユーザー名とパスワードを入力して、[登録] をクリックします。

    security-membership-3

    スタート サイト テンプレートから Web サイトを作成したときに、StarterSite.sdf という名前のデータベースがサイトの App_Data フォルダーに作成されました。 登録中に、ユーザー情報がそのデータベースに追加されます。 SMTP 値を設定すると、登録を完了できるように、使用したメール アドレスにメッセージが送信されます。

    security-membership-4

  11. メール プログラムにアクセスし、確認コードとサイトへのハイパーリンクが表示されたメッセージを見つけます。

  12. ハイパーリンクをクリックしてアカウントをアクティブにします。 確認のハイパーリンクをクリックすると、登録の確認ページが開きます。

    security-membership-5

  13. [ログイン] リンクをクリックしてから、登録したアカウントを使用してログインします。

    ログインすると、[ログイン] リンクと [登録] リンクが [ログアウト] リンクに置き換えられます。 ログイン名がリンクとして表示されます。 (このリンクを使用すると、パスワードを変更できるページに移動できます)。

    security-membership-6

    Note

    既定では、ASP.NET Web ページは、クリア テキスト (人間が判読できるテキスト) でサーバーに資格情報を送信します。 運用サイトでは、セキュリティで保護された HTTP (https://、"Secure Sockets Layer" または SSL とも呼ばれます) を使用して、サーバーと交換される機密情報を暗号化する必要があります。 前の例のように WebMail.EnableSsl=true を設定することで、SSL を使用してメール メッセージを送信する必要があります。 SSL の詳細については、Web 通信のセキュリティ保護: 証明書、SSL、および https:// に関する記事を参照してください。

サイトのその他のメンバーシップ機能

サイトには、ユーザーが自分のアカウントを管理できるその他の機能が含まれています。 ユーザーは次の操作を行うことができます。

  • パスワードを変更します。 ログイン後、ユーザー名 (リンク) をクリックできます。 これにより、新しいパスワードを作成できるページ (Account/ChangePassword.cshtml) に移動します。
  • 忘れたパスワードを回復します。 ログイン ページには、ユーザーがメール アドレスを入力できるページ (Account/ForgotPassword.cshtml) に移動するリンク (パスワードを忘れましたか?) があります。 サイトは、新しいパスワードを設定するためにクリックできるリンク (Account/PasswordReset.cshtml) を含むメール メッセージを送信します。

後で説明するように、ユーザーが外部サイトを使用してログインできるようにすることもできます。

メンバー専用ページを作成する

ひとまず、すべてのユーザーが Web サイトのすべてのページを閲覧できます。 しかし、ログインしたユーザー (つまりメンバー) のみに使用可能なページが必要な場合があります。 ASP.NET を使用すると、ログインしているメンバーのみがアクセスできるページを作成できます。 通常、匿名ユーザーがメンバー専用ページにアクセスしようとした場合、それらのユーザーをログイン ページにリダイレクトします。

この手順では、ログインしているユーザーのみに使用可能なページを含むフォルダーを作成します。

  1. サイトのルートで、新しいフォルダーを作成します。 (リボンで、[新規] の下の矢印をクリックして、[新しいフォルダー] を選びます)。

  2. 新しいフォルダーに Members という名前を付けます。

  3. Members フォルダー内に新しいページを作成し、MembersInformation.cshtml という名前を付けます。

  4. 既存のコンテンツを次のコードとマークアップに置き換えます。

    @{
        if (!WebSecurity.IsAuthenticated) {
            Response.Redirect("~/Account/Login?returnUrl="
                + Request.Url.LocalPath);
        }
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Members Information";
    }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>Members Information</title>
      </head>
      <body>
        <p>You can only see this information if you've logged into the site.</p>
      </body>
    </html>
    

    このコードは、WebSecurity オブジェクトの IsAuthenticated プロパティをテストします。これはユーザーがログインしている場合、true を返します。 ユーザーがログインしていない場合、コードは Account フォルダーの Login.cshtml ページにユーザーを送信するために Response.Redirect を呼び出します。

    リダイレクトの URL には、現在のページのパスを設定するために Request.Url.LocalPath を使用する returnUrl クエリ文字列値が含まれています。 クエリ文字列の returnUrl 値をこのように設定し、さらに戻り URL がローカル パスの場合、ログイン ページはログイン後にユーザーをこのページに返します。

    このコードは、_SiteLayout.cshtml ページをレイアウト ページとして設定もします。 (レイアウト ページの詳細については、「ASP.NET Web ページ サイトでの一貫性のあるレイアウトの作成」を参照してください)。

  5. サイトを実行します。 まだログインしている場合は、ページの上部にある [ログアウト] ボタンをクリックします。

  6. ブラウザーで、ページ /Members/MembersInformation を要求します。 たとえば、URL は次のようになります。

    http://localhost:38366/Members/MembersInformation

    (ポート番号 (38366) は、ご使用の URL では異なる可能性があります)。

    ログインしていないため、Login.cshtml ページにリダイレクトされます。

  7. 前に作成したアカウントを使用してログインします。 MembersInformation ページにリダイレクトされます。 ログインしているため、今回はページの内容が表示されます。

複数のページへのアクセスをセキュリティで保護するために、次の操作を行うことができます。

  • 各ページにセキュリティ チェックを追加します。
  • 保護されたページを保持するフォルダーに _PageStart.cshtml ページを作成し、そこにセキュリティ チェックを追加します。 _PageStart.cshtml ページは、フォルダー内のすべてのページに対してグローバル ページの一種として機能します。 この手法の詳細については、「ASP.NET Web ページのサイト全体の動作のカスタマイズ」を参照してください。

ユーザーのグループ (ロール) に対してセキュリティを作成する

サイトに多数のメンバーが含まれる場合は、ユーザーにページを表示する前に、各ユーザーのアクセス許可を個別にチェックすることは非効率です。 代わりに、個々のメンバーが属するグループ ("ロール") を作成できます。 これで、ロールに基づいてアクセス許可をチェックできます。 このセクションでは、"admin" ロールを作成し、次にそのロールに含まれる (属している) ユーザーがアクセスできるページを作成します。

ASP.NET メンバーシップ システムは、ロールをサポートするようにセットアップされています。 ただし、メンバーシップの登録およびログインとは異なり、スターター サイト テンプレートには、ロールの管理に役立つページが含まれていません。 (ロールの管理は、ユーザー タスクではなく管理タスクです)。ただし、WebMatrix のメンバーシップ データベースに直接グループを追加できます。

  1. WebMatrix で、[データベース] ワークスペース セレクターをクリックします。

  2. 左側のウィンドウで StarterSite.sdf ノードを開き、[テーブル] ノードを開き、webpages_Roles テーブルをダブルクリックします。

    security-membership-7

  3. "admin" という名前のロールを追加します。 RoleId フィールドに自動的にデータが設定されます。 (これは主キーであり、「ASP.NET Web ページ サイトでのデータベースの操作の概要」で説明するように ID フィールドになるように設定されます)。

  4. RoleId フィールドの値を書き留めておきます。 (これが定義する最初のロールの場合は、1 になります)。

    security-membership-8

  5. webpages_Roles テーブルを閉じます。

  6. UserProfile テーブルを開きます。

  7. テーブル内の 1 人以上のユーザーの UserId 値を書き留めて、テーブルを閉じます。

  8. webpages_UserInRoles テーブルを開き、UserIDRoleID 値をテーブルに入力します。 たとえば、ユーザー 2 を "admin" ロールに挿入するには、次の値を入力します。

    security-membership-9

  9. webpages_UsersInRoles テーブルを閉じます。

    ロールが定義されたので、そのロールに含まれるユーザーがアクセスできるページを構成できます。

  10. Web サイトのルート フォルダーで、AdminError.cshtml という名前の新しいページを作成し、既存のコンテンツを次のコードに置き換えます。 これが、ページへのアクセスを許可されない場合にユーザーがリダイレクトされるページになります。

    @{
        Layout = "~/_SiteLayout.cshtml";
        PageData["Title"] = "Admin-only Error";
    }
    <p>You must log in as an admin to access that page.</p>
    
  11. Web サイトのルート フォルダーで、AdminOnly.cshtml という名前の新しいページを作成し、既存のコードを次のコードに置き換えます。

    @{
        Layout = "~/_SiteLayout.cshtml";
        PageData["Title"] = "Administrators only";
    }
    
    @if ( Roles.IsUserInRole("admin")) {
        <span> Welcome <b>@WebSecurity.CurrentUserName</b>! </span>
    }
    else {
         Response.Redirect("~/AdminError");
    }
    

    Roles.IsUserInRole メソッドは、現在のユーザーが指定されたロール (この場合は "admin" ロール) のメンバーである場合に true を返します。

  12. ブラウザーで Default.cshtml を実行しますが、ログインしないでください。 (既にログインしている場合は、ログアウトします)。

  13. ブラウザーのアドレス バーで、URL に AdminOnly を追加します。 (つまり、AdminOnly.cshtml ファイルを要求します)。現在、"admin" ロールのユーザーとしてログインしていないため、AdminError.cshtml ページにリダイレクトされます。

  14. Default.cshtml に戻り、"admin" ロールに追加したユーザーとしてログインします。

  15. AdminOnly.cshtml ページを参照します。 今回はページが表示されます。

自動プログラムが Web サイトに参加できないようにする

ログイン ページは、自動プログラム ("Web ロボット" や "ボット" と呼ばれる場合もあります) が Web サイトに登録することを阻止しません。 この手順では、登録ページに対して ReCaptcha テストを有効にする方法について説明します。

/media/38777/ch16securitymembership-18.jpg

  1. Web サイトを ReCaptcha サービスに登録します。 登録が完了すると、公開キーと秘密キーを受け取ります。

  2. ASP.NET Web ページ サイトへのヘルパーのインストール」の中で説明されているように、(まだ行っていない場合は) ASP.NET Web ヘルパー ライブラリを Web サイトに追加します。

  3. Account フォルダーで、Register.cshtml という名前のファイルを開きます。

  4. ページの上部にあるコードで、次の行を見つけ、// コメント文字を削除してコメントを解除します。

    if (!ReCaptcha.Validate("PRIVATE_KEY")) {
        ModelState.AddError("recaptcha", "Captcha response was not correct");
    }
    
  5. PRIVATE_KEY を自分の ReCaptcha 秘密キーに置き換えます。

  6. ページのマークアップで、ページ マークアップの次の行の周囲から @**@ のコメント文字を削除します。

    @ReCaptcha.GetHtml("PUBLIC_KEY", theme: "white")
    @Html.ValidationMessage("recaptcha")
    
  7. PUBLIC_KEY をご自分のキーに置き換えます。

  8. まだ削除していない場合は、「To enable CAPTCHA verification ... (CAPTCHA 検証を有効にするには ...)」で始まるテキストを含む <div> 要素を削除します。 (<div> 要素とその内容全体を削除します)。

  9. ブラウザーで Default.cshtml を実行します。 サイトにログインしている場合は、[ログアウト] リンクをクリックします。

  10. [登録] リンクをクリックし、CAPTCHA テストを使用して登録をテストします。

    security-membership-10

ReCaptcha ヘルパーの詳細については、「CAPTCHA を使用することで、自動化されたプログラム (ボット) による ASP.NET Web サイトの利用を防ぐ」を参照してください。

外部サイトを使用してユーザーがログインできるようにする

スターター サイト テンプレートには、ユーザーが Facebook、Windows Live、Twitter、Google、Yahoo を使用してログインできるようにするコードとマークアップが含まれています。 既定では、この機能は有効になっていません。 ユーザーがこれらの外部プロバイダーを使用してログインできるようにする一般的な手順は次のとおりです。

  • サポートする外部サイトを決定します。
  • 必要に応じて、そのサイトにアクセスし、ログイン アプリをセットアップします。 (たとえば、Facebook ログインを許可するには、これを行う必要があります)。
  • ご使用のサイトで、プロバイダーを構成します。 ほとんどの場合、_AppStart.cshtml ファイル内の一部のコードのコメントを解除するだけです。
  • 登録ページにマークアップを追加して、ユーザーがログイン用の外部サイトにリンクできるようにします。 通常、必要なマークアップをコピーして、テキストを少し変更することが可能です。

順を追った手順については、「ASP.NET Web ページ サイトで外部サイトからのログインを有効にする」を参照してください。

ユーザーは、別のサイトからログイン後にご使用のサイトに戻り、そのログインをご使用のサイトに "関連付けます"。 これにより実質的に、ユーザーの外部ログイン用のメンバーシップ エントリがご使用のサイトに作成されます。 これにより、外部ログインでメンバーシップの通常の機能 (ロールなど) を使用できます。

既存の Web サイトにセキュリティを追加する

この記事のここまでの手順は、Web サイトのセキュリティの基盤としてスターター サイト テンプレートを使用することに依存しています。 スターター サイト テンプレートから開始したり、そのテンプレートに基づいてサイトから関連するページをコピーしたりすることが実用的でない場合は、自分でコーディングすることで、自分のサイトに同じ種類のセキュリティを実装できます。 登録、ログインなどの同じ種類のページを作成し、次にヘルパーとクラスを使用してメンバーシップをセットアップします。

基本的なプロセスは、ブログ投稿「ASP.NET Razor セキュリティを実装する最も基本的な方法 (英語)」で説明されています。 ほとんどの作業は、WebSecurity ヘルパーの次のメソッドとプロパティを使用して行われます。

ロールを管理するために、ブログ エントリで説明されているように、Roles クラスと Membership クラスを使用できます。

その他のリソース