Posted at

ASP.NET Core の RazorPage で エリアやページごとにアクセス制限をかける


はじめに

業務で ASP.Net Core MVC を使っていたのですが、RazorPage でウェブアプリを作ったことはなかったので、勉強かねて仮想的なECサイトを作っていました。

その中で、いくつかハマった事をまとめておこうと思います。

今回は、アクセス制限のかけ方についてまとめます。


想定している状況

デジタル作品をアップロードして、販売できるECサイトを想定して解説します。


フォルダおよびURLの構成

以下は、ソリューション内のフォルダ構成で、カッコ内はURLです。

解説に必要な部分だけ示しています。

なお、フォルダ構成と URL は一致しているわけではありません。

例えば、カートページは Purchase フォルダ内のページですが、 /Cart でアクセスできるような状況を想定しています。

/

├── Areas/
│ └── Seller/
│ └── Pages/
│ ├── Items/
│ │ └── Manage/
│ │ ├── Index.cshtml(/Seller/Items/Manage)
│ │ ├── ...
│ │
│ └── Register.cshtml(/Seller/Items/Register)
├── Pages/
│ ├── Purchase/
│ │ ├── Cart.cshtml(/Cart)
│ │ ├── Payment.cshtml(/Purchase/Payment)
│ │ ├── Confirm.cshtml(/Purchase/Confirm)
│ │ ├── ...
│ │
│ └── User
│ ├── Purchase.cshtml(/User/Purchase)
│ ├── Profile.cshtml(/User/:Uid/Profile)
│ ├── ...

└── StartUp.cs


アクセス制限の設定方法

ここでは、StartUp.cs 内で設定する方法を解説します。

以下のコードは、すべて ConfigureService 内に記述します。


販売者関連ページ(/Areas/Seller/)

Seller エリアにあるすべてのページは、ログインしていて、なおかつロールに"Seller"が設定されているユーザーのみアクセスできるように設定します。

事前に、ポリシーを追加しておきます。

services.AddAuthorization(

{
// アクセス制限用ポリシーを追加
options.AddPolicy("SellerPolicy", policy => policy.RequireRole("Seller"));
});

このアクセスポリシーを、Seller エリアに適用します。

エリアに承認規則を設定するには、AuthorizeAreaFolder を使います。

フォルダーパスは、エリアフォルダを基準にした相対パスを設定します。

AuthorizeAreaFolder("エリア名", "フォルダーパス", "ポリシー")

実際のコードは以下のようになります。

services.AddMvc().AddRazorPagesOptions(options =>

{
// 販売者の作品関連ページ
options.Conventions.AuthorizeAreaFolder("Seller", "/Items", "SellerPolicy");
});


購入関連ページ(/Pages/Purchase/)

以下のような承認規則を設定します。

『購入関連のページは、ログインユーザー以外アクセスできないようにしたいが、カートページだけはログインしていないユーザーもアクセスできるようにする』

この場合、規則を設定する順番が重要になります。

まず始めに、Purchase フォルダーに対してログインユーザー以外アクセスできないように設定します。

その後、カートページに対して、AllowAnonymousToPage を使って、だれでもアクセスできるように設定をしすます。

AllowAnonymousToPage("ページ(.cshtml)パス")

実際のコードは以下のようになります。

services.AddMvc().AddRazorPagesOptions(options =>

{
// 購入関連ページ
options.Conventions.AuthorizeFolder("/Purchase");
// カートページはログインしていなくても許可
options.Conventions.AllowAnonymousToPage("/Purchase/Cart");

// NOTE: まとめて以下のように書いても良い
// options.Conventions
// .AuthorizeFolder("/Purchase")
// .AllowAnonymousToPage("/Purchase/Cart");
});

Authorize~ よりも AllowAnonymous~ の方が強いので、先に .AllowAnonymousToFolder("/Purchase") とした後、.AuthorizePage("/Purchase/カード以外のページ") とやっても Purchase 以下のページはだれでもアクセスできてしまいます。


登録ユーザー関連ページ(/User/)

ユーザー関連ページの購入作品一覧ページのみ、ログインしているユーザー本人がアクセスできるように設定します。

特定のページにのみ承認規則を設定するには、AuthorizePage を使います。

AuthorizePage("ページパス")

実際のコードは以下のようになります。

services.AddMvc().AddRazorPagesOptions(options =>

{
// 購入作品一覧ページ
options.Conventions.AuthorizePage("/User/Purchase");
});


コード全体

services.AddAuthorization(

{
// アクセス制限用ポリシーを追加
options.AddPolicy("SellerPolicy", policy => policy.RequireRole("Seller"));
});

services.AddMvc().AddRazorPagesOptions(options =>
{
// 販売者の作品関連ページ
options.Conventions.AuthorizeAreaFolder("Seller", "/Items","SellerPolicy");
// 購入関連ページ
options.Conventions.AuthorizeFolder("/Purchase");
// カートページはログインしていなくても許可
options.Conventions.AllowAnonymousToPage("/Purchase/Cart");
// 購入作品一覧ページ
options.Conventions.AuthorizePage("/User/Purchase");
});


参考

他にもアクセス制限のかけ方はあります。詳しく知りたい方は、公式ページを参照してください。

公式 - Razor Pages authorization conventions in ASP.NET Core

未完成ですが、デジタルデータを販売できるECサイトを想定したプロジェクトを用意したので、該当するファイルへのリンクも貼っておきます。

GitHub - EStalls StartUp.cs