Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

業務で 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

tatsuteb
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away