Blazor Serverではメールアドレスとパスワードによるユーザー認証機能を自動生成できます。
しかし、自動生成しただけではコードまでは自動的に生成されません。
この記事では、ユーザー認証機能とそのコードの自動生成を行う方法を紹介します。
- dotnet new コマンドで BlazorServerプロジェクトを作成する
- 個別認証で生成した場合のユーザー情報DB
- NuGetパッケージと dotnet tools のインストール
- dotnet aspnet-codegenerator コマンドの動作確認(ヘルプ表示)
- コード生成可能なファイルリストの表示
- コード自動生成の実行
- 'ApplicationDbContext' is an ambiguous reference エラーの対処法
- InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /_Host, area: }. エラーの対処法
- コード自動生成後のプロジェクトフォルダ構成
- 終わりに
- 参考URL
- Blazor のおすすめ本
dotnet new コマンドで BlazorServerプロジェクトを作成する
認証機能を付加したBlazorServerプロジェクトの作成は以下のコマンドで行います。
dotnet new blazorserver -au Individual
-au
オプションの引数は以下のものを指定できます。
-au(--auth)オプションに指定可能な値
値 | 説明 |
---|---|
None | 認証は行われません (既定) |
ndividual | 個別認証です |
ndividualB2C | Azure AD B2C での個別認証 |
SingleOrg | 単一のテナントに対する組織認証 |
MultiOrg | 複数のテナントに対する組織認証です |
Windows | Windows 認証 |
参考URL
個別認証で生成した場合のユーザー情報DB
-au Individual
で生成した場合、プロジェクトフォルダ直下にapp.db
が作成され、ここにユーザー情報が格納されます。
app.db
には、以下のテーブルが含まれます。
ubuntu@ip-172-31-31-143:~/remoteDir/usefuledge20211023/blazorauthsample$ sqlite3 app.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> .tables
AspNetRoleClaims AspNetUserLogins AspNetUsers
AspNetRoles AspNetUserRoles __EFMigrationsHistory
AspNetUserClaims AspNetUserTokens
このうち、AspNetUsers
テーブルに、ユーザーIDやメールアドレス、暗号化されたパスワードなどが格納されます。
AspNetUsers
テーブルの定義は以下の通りです。
sqlite> .head on
sqlite> .mode column
sqlite> pragma table_info('AspNetUsers');
cid name type notnull dflt_value pk
---------- ---------- ---------- ---------- ---------- ----------
0 Id TEXT 1 1
1 AccessFail INTEGER 1 0
2 Concurrenc TEXT 0 0
3 Email TEXT 0 0
4 EmailConfi INTEGER 1 0
5 LockoutEna INTEGER 1 0
6 LockoutEnd TEXT 0 0
7 Normalized TEXT 0 0
8 Normalized TEXT 0 0
9 PasswordHa TEXT 0 0
10 PhoneNumbe TEXT 0 0
11 PhoneNumbe INTEGER 1 0
12 SecuritySt TEXT 0 0
13 TwoFactorE INTEGER 1 0
14 UserName TEXT 0 0
sqlite>
ユーザー登録すると、以下のようなレコードが格納されます。
sqlite> select * from aspnetusers;
Id AccessFailedCount ConcurrencyStamp Email EmailConfirmed LockoutEnabled LockoutEnd NormalizedEmail NormalizedUserName PasswordHash PhoneNumber PhoneNumberConfirmed SecurityStamp TwoFactorEnabled UserName
------------------------------------ ----------------- ------------------------------------ ------------------ -------------- -------------- ---------- ------------------ ------------------ ------------------------------------------------------------------------------------ ----------- -------------------- -------------------------------- ---------------- ------------------
a4cff7d9-185b-40a8-b8c9-d521b94a8b9c 0 7279bfcc-b974-4db6-8acb-1bdb0964b74a sxxx7@xxx.com 1 1 SXXX7@XXX.COM SXXX7@XXX.COM AQAAAAEAACcQAAAAEBPeHWT8NH482ZzQJtvQ7Hgt/3xTEHohryvzPbx//gQhVK5yTMPeEfBIjjgPnxgf5A== 0 PQ7WGLR27FIQ2537Y6DFOQFPMVU45AKI 0 sxxx7@xxx.com
sqlite>
NuGetパッケージと dotnet tools のインストール
コード生成のため、以下のNuGetパッケージと dotnet tools をインストールしていきます。
Microsoft.VisualStudio.Web.CodeGeneration.Design
後述するdotnet-aspnet-codegenerator
コマンドが含まれています。
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
参考URL : NuGet Gallery
dotnet-aspnet-codegenerator
dotnet aspnet-codegenerator
コマンドを使うため、インストールしていきます。
dotnet tool install -g dotnet-aspnet-codegenerator
参考URL : dotnet-aspnet-codegenerator
コード生成に必要な NuGet Package
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet aspnet-codegenerator コマンドの動作確認(ヘルプ表示)
以下のコマンドを実行して、dotnet aspnet-codegenerator
コマンドが正しく使用できるか確認しましょう。
dotnet aspnet-codegenerator identity -h
正しく使用できる場合、以下のようにコマンドの使い方が表示されます。
Usage: aspnet-codegenerator [arguments] [options]
Arguments:
generator Name of the generator. Check available generators below.
Options:
-p|--project Path to .csproj file in the project.
-n|--nuget-package-dir
-c|--configuration Configuration for the project (Possible values: Debug/ Release)
-tfm|--target-framework Target Framework to use. (Short folder name of the tfm. eg. net46)
-b|--build-base-path
--no-build
Selected Code Generator: identity
Generator Options:
--dbContext|-dc : Name of the DbContext to use, or generate (if it does not exist).
--files|-fi : List of semicolon separated files to scaffold. Use the --listFiles option to see the available options.
--listFiles|-lf : Lists the files that can be scaffolded by using the '--files' option.
--userClass|-u : Name of the User class to generate.
--useSqLite|-sqlite : Flag to specify if DbContext should use SQLite instead of SQL Server.
--force|-f : Use this option to overwrite existing files.
--useDefaultUI|-udui : Use this option to setup identity and to use Default UI.
--layout|-l : Specify a custom layout file to use.
--generateLayout|-gl : Use this option to generate a new _Layout.cshtml
--bootstrapVersion|-b : Specify the bootstrap version. Valid values: '3', '4'. Default is 4.
コード生成可能なファイルリストの表示
コード生成が可能なファイルリストは、以下のコマンドで確認できます。
dotnet aspnet-codegenerator identity -sqlite -dc MyApplication.Data.ApplicationDbContext --listFiles
Building project ...
Finding the generator 'identity'...
Running the generator 'identity'...
File List:
Account._StatusMessage
Account.AccessDenied
Account.ConfirmEmail
Account.ConfirmEmailChange
Account.ExternalLogin
Account.ForgotPassword
Account.ForgotPasswordConfirmation
Account.Lockout
Account.Login
Account.LoginWith2fa
Account.LoginWithRecoveryCode
Account.Logout
Account.Manage._Layout
Account.Manage._ManageNav
Account.Manage._StatusMessage
Account.Manage.ChangePassword
Account.Manage.DeletePersonalData
Account.Manage.Disable2fa
Account.Manage.DownloadPersonalData
Account.Manage.Email
Account.Manage.EnableAuthenticator
Account.Manage.ExternalLogins
Account.Manage.GenerateRecoveryCodes
Account.Manage.Index
Account.Manage.PersonalData
Account.Manage.ResetAuthenticator
Account.Manage.SetPassword
Account.Manage.ShowRecoveryCodes
Account.Manage.TwoFactorAuthentication
Account.Register
Account.RegisterConfirmation
Account.ResendEmailConfirmation
Account.ResetPassword
Account.ResetPasswordConfirmation
RunTime 00:00:05.95
コード自動生成の実行
以下のコマンドで、すべてのコードの自動生成(スキャフォールディング)を実行します。
このコマンドは、SQLiteDBを使用したユーザー認証のコード生成です。
MyApplication
の部分はプロジェクト名に変更してください。
dotnet aspnet-codegenerator identity -sqlite -dc MyApplication.Data.ApplicationDbContext
自動生成対象のファイルを指定する場合は、--files
オプションを使用します。
dotnet aspnet-codegenerator identity -sqlite -dc MyApplication.Data.ApplicationDbContext --files "Account.Register;Account.Login"
'ApplicationDbContext' is an ambiguous reference エラーの対処法
dotnet run
したときに、以下のように'ApplicationDbContext' is an ambiguous reference
エラーが発生することがあります。
/home/ubuntu/remoteDir/usefuledge20211023/blazorauthsample/Program.cs(15,31): error CS0104: 'ApplicationDbContext' is an ambiguous reference between 'blazorauthsample.Data.ApplicationDbContext' and 'MyApplication.Data.ApplicationDbContext' [/home/ubuntu/remoteDir/usefuledge20211023/blazorauthsample/blazorauthsample.csproj]
エラーが発生した場合は、Program.cs
のusing句から、using MyApplication.Data;
をコメントアウトしましょう。
using blazorauthsample.Areas.Identity;
using blazorauthsample.Data;
//using MyApplication.Data;
InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /_Host, area: }. エラーの対処法
dotnet run
したときに、以下のようにInvalidOperationException
が発生することがあります。
InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /_Host, area: }.
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.DynamicPageEndpointMatcherPolicy.ApplyAsync(HttpContext httpContext, CandidateSet candidates)
この場合、プロジェクトファイル(.csprojファイル)の<PropertyGroup>
に<UseRazorSourceGenerator>false</UseRazorSourceGenerator>
を追加しましょう。
<PropertyGroup>
<UseRazorSourceGenerator>false</UseRazorSourceGenerator>
</PropertyGroup>
参考URL
コード自動生成後のプロジェクトフォルダ構成
コード自動生成後は、Areas
フォルダなどにコードが生成されます。
.
├── ./App.razor
├── ./Areas
│ └── ./Areas/Identity
│ ├── ./Areas/Identity/Data
│ │ └── ./Areas/Identity/Data/ApplicationDbContext.cs
│ ├── ./Areas/Identity/Pages
│ │ ├── ./Areas/Identity/Pages/Account
│ │ │ ├── ./Areas/Identity/Pages/Account/AccessDenied.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/AccessDenied.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ConfirmEmail.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ExternalLogin.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ForgotPassword.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/Lockout.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/Lockout.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/LogOut.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/Login.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/Login.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/LoginWith2fa.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/Logout.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/Logout.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/Manage
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/Email.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/Email.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/Index.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/Index.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ManageNavPages.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/PersonalData.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/PersonalData.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/SetPassword.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/_Layout.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml
│ │ │ │ ├── ./Areas/Identity/Pages/Account/Manage/_StatusMessage.cshtml
│ │ │ │ └── ./Areas/Identity/Pages/Account/Manage/_ViewImports.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/Register.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/Register.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/RegisterConfirmation.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ResetPassword.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ResetPassword.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml
│ │ │ ├── ./Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs
│ │ │ ├── ./Areas/Identity/Pages/Account/_StatusMessage.cshtml
│ │ │ └── ./Areas/Identity/Pages/Account/_ViewImports.cshtml
│ │ ├── ./Areas/Identity/Pages/Error.cshtml
│ │ ├── ./Areas/Identity/Pages/Error.cshtml.cs
│ │ ├── ./Areas/Identity/Pages/Shared
│ │ │ └── ./Areas/Identity/Pages/Shared/_LoginPartial.cshtml
│ │ ├── ./Areas/Identity/Pages/_ViewImports.cshtml
│ │ └── ./Areas/Identity/Pages/_ViewStart.cshtml
│ └── ./Areas/Identity/RevalidatingIdentityAuthenticationStateProvider.cs
├── ./Data
│ ├── ./Data/ApplicationDbContext.cs
│ ├── ./Data/Migrations
│ │ ├── ./Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs
│ │ ├── ./Data/Migrations/00000000000000_CreateIdentitySchema.cs
│ │ └── ./Data/Migrations/ApplicationDbContextModelSnapshot.cs
│ ├── ./Data/WeatherForecast.cs
│ └── ./Data/WeatherForecastService.cs
├── ./Pages
│ ├── ./Pages/Counter.razor
│ ├── ./Pages/Error.cshtml
│ ├── ./Pages/Error.cshtml.cs
│ ├── ./Pages/FetchData.razor
│ ├── ./Pages/Index.razor
│ ├── ./Pages/Shared
│ │ ├── ./Pages/Shared/_Layout.cshtml
│ │ ├── ./Pages/Shared/_LoginPartial.cshtml
│ │ └── ./Pages/Shared/_ValidationScriptsPartial.cshtml
│ ├── ./Pages/_Host.cshtml
│ ├── ./Pages/_Layout.cshtml
│ ├── ./Pages/_ViewImports.cshtml
│ └── ./Pages/_ViewStart.cshtml
├── ./Program.cs
├── ./Properties
│ └── ./Properties/launchSettings.json
├── ./ScaffoldingReadMe.txt
├── ./Shared
│ ├── ./Shared/LoginDisplay.razor
│ ├── ./Shared/MainLayout.razor
│ ├── ./Shared/MainLayout.razor.css
│ ├── ./Shared/NavMenu.razor
│ ├── ./Shared/NavMenu.razor.css
│ └── ./Shared/SurveyPrompt.razor
├── ./_Imports.razor
├── ./app.db
├── ./appsettings.Development.json
├── ./appsettings.json
終わりに
この記事で自動生成したユーザー認証の各ページは、カスタマイズが可能です。
詳細は以下にまとめていますので、ご覧ください。
BLAZOR SERVER で自動生成したユーザー認証機能の各画面をカスタマイズする方法
参考URL
Blazor のおすすめ本
私もBlazorを用いていくつかウェブアプリを開発しました。フレームワークがとても分かりやすく、簡単にSPAを作れることが楽しいと感じています。
Blazor wasm であればAWS S3のようなウェブホスティングサービスでアプリを公開することもできますし、Blazor Serverアプリであれば簡単に2要素認証を構築できます。
Blazor は現在も開発が進められているフレームワークですので本の情報は少しずつ古くなってしまいますが、全体的・体系的に学ぶには、本はとても有力なツールです。
電子書籍になっていますので、まずは試し読みから始めてはいかがでしょうか。
章 | 内容 |
---|---|
第1章 | Blazorの仕組み |
第2章 | 開発環境 |
第3章 | 最初のBlazorアプリ |
第4章 | コンポーネント |
第5章 | データバインディング |
第6章 | イベント処理 |
第7章 | Razor記法 |
第8章 | フォームと検証 |
第9章 | データベースアクセス |
第10章 | Web APIの活用 |
第11章 | SVGの活用 |
第12章 | JavaScriptとの連携 |
コメント