セキュリティ Server

【Udemy学習#4】ASP.NET MVCでメンバーシッププロバイダーを使ってログイン認証機能を実装

オンラインUdemyの講座を使ってASP.NET MVCの学習を進めています。

今回は、「メンバーシッププロバイダーを使ってログイン機能を実装する」方法をやりました。

自分用のメモとしてブログを活用しているので講座の内容にも沿ってないし詳細は書いておりませんので御注意ください。

講座の内容に沿って作業

Modelsでクラス作成(CustomMembershipProvider.cs)

クラス名も指示されるままに同じネーミングで進めていきました。

先頭文字大文字にする仕様は学習しましたが、途中で大文字を入れていくのはなぜなのでしょうか?

Memberを打ち間違えてMenberにしたら抽象クラスの実装がでてきませんでした(´;ω;`)ウゥゥ

ぐにゃぐにゃの赤い波線が出ているので、「抽象クラスの実装」をしました。

はい!出たー専門用語!?

もう調べるだけで時間が掛かってしまいますし、調べても意味が理解できないのですよね。

とりあえず、Qiitaさんのページだけ読みました。

ビビらす先に行こう!

なんだか勝手に大量のコードが出現

しました。

でも、使うのは数行のコードらしい。

        public override bool ValidateUser(string username, string password)
        {
            if ("administrator".Equals(username) && "password".Equals(password))
            {
                return true;
            }
            if ("user".Equals(username) && "password".Equals(password))
            {
                return true;
            }
            return false;
        }

上記の部分を追加しました。

  • administrator  と password のセットの時は、true
  • user と password のセットの時は、true

になり、それ以外は、falseとなり、ログインできなくするようです。

ちなみに、この作業は、メンバーシッププロバイダーの設定ということで、マイクロソフトのページから引用すれば、「ASP.NET メンバーシッププロバイダーは、ユーザーが一意のユーザー名とパスワードの組み合わせを作成できるようにする Web サイトを ASP.NET 開発者が作成できるようにする機能」という事です。

Modelsでクラス作成(CustomRoleProvider.cs)

また、ロールと言う専門用語がでてきましたが、マイクロソフトの解説ページによれば、「ASP.NET ロールプロバイダー (ASP.NET メンバーシッププロバイダーと共に) は、ASP.NET 開発者がサイトを使用してアカウントを作成し、承認のためにロールを割り当てることができる Web サイトを作成できるようにする機能です。 この機能を使用すれば、ユーザーはだれでもサイトでアカウントを作成し、そのサイトにログインしてサービスに排他的にアクセスできます。」という事です。

はい!出たー専門用語だらけ?

ロールって何!?

変えた部分は、下記のようになります。

        public override string[] GetRolesForUser(string username)
        {
            if ("administrator".Equals(username))
            {
                return new string[] { "Administrator" };
            }
            return new string[] { "User" };
        }

この部分で、usernameがadministratorだったら、ロールにAdministratorを返し、違ったら、Userを返すようにしているようです。

もう一ヶ所を追加

        public override bool IsUserInRole(string username, string roleName)
        {
            if ("administrator".Equals(username)  && "Administrators".Equals(roleName))
            {
                return true;
            }
            if ("user".Equals(username) && "Users".Equals(roleName))
            {
                return true;
            }
            return false;
        }

この内容は、usernameが

  • administratorで、ロールが、Administratorsならtrue
  • user で、ロールが、Usersならtrue

それ以外は、falseってことです。

Modelsでクラス作成(LoginViewModel.cs)

using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace TodoApp.Models
{
    publicRoleoginViewModel
    {
        [Required]
        [DisplayName("ユーザー名")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [DisplayName("パスワード")]
        public string Password { get; set; }

    }
}

これは、データベースの設定ですかね!?

[Required]は必須という事ですね。

[DataType(DataType.Password)]の部分は、パスワードだよっていう設定ですね。

Controllersでコントローラー作成(LoginController.cs)

MVC5コントローラー空」にてコントローラーを追加しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using TodoApp.Models;

namespace TodoApp.Controllers
{
    [AllowAnonymous]
    public class LoginController : Controller
    {
        readonly CustomMembershipProvider membershipProvider = new CustomMembershipProvider();

        // GET: Login
        public ActionResult Index()
        {
            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index([Bind(Include = "UserName.Password")] LoginViewModel model)
        {
            if(ModelState.IsValid)
            { 
                if (this.membershipProvider.ValidateUser(model.UserName,model.Password))
                {
                    FormsAuthentication.SetAuthCookie(model.UserName, false);
                    return RedirectToAction("Index", "Todoes");
                }
            }

            ViewBag.Message = "ログインに失敗しました。";
            return View(model);
        }
        public ActionResult SignOut()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Index");
        }
     }
}

[AllowAnonymous]で認証して無くても表示できるようにしているようです。

あとは、オンライン講座では全部を説明しながら進められていますが、自分には理解できないので、ありのままを受け入れてコードを入力してみました。

Views>>Loginにindex.cshtmlを作成

LoginController.csのpublic Actionresult Index()のindexの上で右クリックしてビューの追加をします。

上の図のように設定することで、Viewが作成されるようです。

注意

上の図では、public class View : Controllerとなっていますが、ミスであり、このままですと、Viewsの中に、Viewがつくられて、その中にIndex.cshtmlが作成されます。

正解は、public class LoginController : Controllerとなります。

Views>>Login内のIndex.cshtmlを編集

タイトルなどでIndexになっている部分を SignInに変更しました。

次に、認証失敗時の表示として、下記を追加

@if(!string.IsNullOrEmpty(ViewBag.Message))
{
    <p class="text-danger">@ViewBag.Message</p>
}

そして、トップの認証画面なので、戻るボタンが必要ないので下記を削除しました。

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

共通レイアウトの編集

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <div class="container">
        @if(Request.IsAuthenticated)
        {
            @Html.ActionLink("ログアウト","SignOut",new { Controller = "Login"})
        }
    </div>
    <div class="container">
        @RenderBody()
    </div>
</body>
</html>

ログアウトの部分を追加したようです。

TodoesController.csにアクセス制限を付加

認証してなくて、TodoesContllerにアクセスしようとするとIndexに戻されるようになるらしい。

らしいという表現しか理解できてないが悲しい。

Web.configの編集

初期画面をログイン画面に変更する設定をしました。

他、認証の設定をしているようですが、全く何やっているのか理解できません。

<system.web>の部分に下記のように追加しました

  <system.web>
    <compilation debug="true" targetFramework="4.7.2"/>
    <httpRuntime targetFramework="4.7.2"/>
    <authentication mode ="Forms">
      <forms loginUrl="~/Login/Index"></forms>
    </authentication>
    <membership defaultProvider="CustomMembershipProvider">
      <providers>
        <clear/>
        <add name="CustomMembershipProvider" type="TodoApp.Models.CustomMembershipProvider"/>
      </providers>
    </membership>
    <roleManager enabled="true" defaultProvider="CustomRoleProvider">
      <providers>
        <clear/>
        <add name="CustomRoleProvider" type="TodoApp.Models.CustomRoleProvider"/>
      </providers>
    </roleManager>    
  </system.web>

とりあえず、長かったですが、ここまでこれました。

さて、デバッグの開始して動作確認をしてみましょう。

想定していたエラーで泣く(デバッグ)

長い道のりもやっとこ終わってデバッグの開始をすると下記のようになりました。

挫折寸前になりました!

エラーは、Models内の、CustomRoleProviderが読めないよっていうことです。

ココに注意

CustomとCustumのスペルミス

コードを入力している時から、これ絶対にスペルミスするだろうなって想定していました。

もっと間違えないような短い略語にした方が良いなとも考えていましたが、何か意味があると困ると思ってオンライン講座と同じ名前を使って進めていました。

モデルの名前の変更でやってみたら・・・

自動で全部変えてくれるんだ!親切!

さて、デバッグの開始・・・できた!!

administrator と password でログインしようとしても、user と password でログインしようとしてもログインに失敗してログインできません。

何で?・・・挫折寸前です。

今日はもう止めて酒飲みます(´;ω;`)ウゥゥ

再度動画を見直して3日目に発見

実際は、心が折れかかっており3日間放置していました。

気を取り直して再度良ーく、動画内のコードを神経質になるくらいに視聴しました。

そして、ようやく発見しました。

ココに注意

コロンとカンマの違い

Visual Studioってサポート機能で、エディター内で波線やコメントが出てきていましたが、場所によっては、スペルミスもコロンとカンマの違いも発見できません。

コロンになっていましたが、カンマに修正

この回の感想

 

途中挫折しそうになりましたが何とか乗り越えました。

 

今回は、ログインユーザーをデータベース化しないで、LoginViewModelという場所に格納して行う認証方法のようですが、ModelsのCustomMembershipProvider.cs内に記述したログイン名とパスワードによってログインする方法と自分は理解しました。

 

WEBシステムを使う上で個別のログイン制限は必要ないが、IDとPWを知らないと仕組みが使えないという感じの制限をかけるには便利な方法ですね。

 

 

-セキュリティ, Server
-, , ,

Translate »

© 2020 PCTips