1. tatsuteb

    Posted

    tatsuteb
Changes in title
+ASP.NET Core の RazorPage で エリアやページごとにアクセス制限をかける
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,166 @@
+# はじめに
+
+業務で 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"が設定されているユーザーのみアクセスできるように設定します。
+
+事前に、ポリシーを追加しておきます。
+
+```csharp
+services.AddAuthorization(
+{
+ // アクセス制限用ポリシーを追加
+ options.AddPolicy("SellerPolicy", policy => policy.RequireRole("Seller"));
+});
+```
+
+このアクセスポリシーを、Seller エリアに適用します。
+エリアに承認規則を設定するには、`AuthorizeAreaFolder` を使います。
+フォルダーパスは、エリアフォルダを基準にした相対パスを設定します。
+
+```csharp
+AuthorizeAreaFolder("エリア名", "フォルダーパス", "ポリシー")
+```
+
+実際のコードは以下のようになります。
+
+```csharp
+services.AddMvc().AddRazorPagesOptions(options =>
+{
+ // 販売者の作品関連ページ
+ options.Conventions.AuthorizeAreaFolder("Seller", "/Items", "SellerPolicy");
+});
+```
+
+## 購入関連ページ(/Pages/Purchase/)
+
+以下のような承認規則を設定します。
+
+『購入関連のページは、ログインユーザー以外アクセスできないようにしたいが、カートページだけはログインしていないユーザーもアクセスできるようにする』
+
+この場合、**規則を設定する順番**が重要になります。
+まず始めに、Purchase フォルダーに対してログインユーザー以外アクセスできないように設定します。
+その後、カートページに対して、`AllowAnonymousToPage` を使って、だれでもアクセスできるように設定をしすます。
+
+```csharp
+AllowAnonymousToPage("ページ(.cshtml)パス")
+```
+
+実際のコードは以下のようになります。
+
+```csharp
+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` を使います。
+
+```csharp
+AuthorizePage("ページパス")
+```
+
+実際のコードは以下のようになります。
+
+```csharp
+services.AddMvc().AddRazorPagesOptions(options =>
+{
+ // 購入作品一覧ページ
+ options.Conventions.AuthorizePage("/User/Purchase");
+});
+```
+
+## コード全体
+
+```csharp
+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](https://docs.microsoft.com/ja-jp/aspnet/core/security/authorization/razor-pages-authorization?view=aspnetcore-2.2#note-on-combining-authorized-and-anonymous-access)
+
+未完成ですが、デジタルデータを販売できるECサイトを想定したプロジェクトを用意したので、該当するファイルへのリンクも貼っておきます。
+
+[GitHub - EStalls StartUp.cs](https://github.com/tatsuteb/EStalls/blob/develop/EStalls/Startup.cs)