WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

.NET 6.0 ASP.NET Identity に MySQL 使用 (その2)

by WebSurfer 2023年2月12日 16:15

.NET 6.0 の ASP.NET MVC アプリで、プロバイダに Oracle 製 MySql.EntityFrameworkCore v6.0.10 を使って、ASP.NET Core Identity のユーザー情報のストアに MySQL を利用する話を書きます。

ASP.NET Identity に MySQL 使用

先の記事「.NET 6.0 ASP.NET Identity に MySQL 使用 (CORE)」では、その時点で Oracle 製 MySql.EntityFrameworkCore は v5.0.8 までしかリリースされていなかったので、プロバイダには Pomelo.EntityFrameworkCore.MySql を使用しています。

その後 Oracle 製 MySql.EntityFrameworkCore の .NET 6.0 用がリリースされたので試してみましたが、v6.0.7 までは Add-Migration に失敗して使えませんでした。

先日バージョンアップの状況を調べてみたら v6.0.10 がリリースされていたので試してみたら Add-Migration は成功するようになってました。その後 Update-Database でデータベースは生成され、Resister でのユーザー登録、Login でのユーザー認証も問題なくできます。(ただし、100% 完全に動くかどうかまでは未検証ですが)

と言うわけで、プロバイダに Oracle 製 MySql.EntityFrameworkCore v6.0.10 を使ってのアプリの作り方を、先の記事の Pomelo.EntityFrameworkCore.MySql と違う点だけ以下に書いておきます。

(1) NuGet パッケージ

NuGet で MySql.EntityFrameworkCore v6.0.10 をインストールします。他に必要なものとバージョンを合わせました。

MySql.EntityFrameworkCore

(2) Program.cs の修正

自動生成されれた Program.cs ファイルで、サービス登録のコードが SQL Server を使うように設定されているはずですが、これを MySQL を使うように変更します。以下のような感じです。

Program.cs の修正

(3) Add-Migration / Update-Database の実行

パッケージマネージャーコンソールから Add-Migration CreateIdentitySchema を実行します (CreateIdentitySchema という名前は任意です)。

xxxxx_CreateIdentitySchema.cs

Migrations と言う名前のフォルダとその中に xxxxx_CreateIdentitySchema.cs というファイル (xxxxx は作成時のタイムスタンプ) が生成されているはずですので確認してください。内容は Pomelo.EntityFrameworkCore.MySql を使った場合と若干異なります。

昔使った MySql.Data.EntityFrameworkCore(今は非推奨)で主キーの長さが指定されてなくて問題となったところは、Pomelo.EntityFrameworkCore.MySql と場合と同様に、varchar(255) に指定されています。

その後、Update-Database を実行すれば接続文字列で指定した名前で MySQL データベースが生成され、その中に ASP.NET Core Identity に必要なテーブルが一式生成されます。

MySQL データベース

Visual Studio から MVC アプリを起動し Register 画面からユーザー登録ができることを確認してください。登録したユーザーは上の MySQL データーベースに反映され、Login 画面から登録した ID とパスワードでログインできるようになります。

この記事の一番上の画像はログインした後で Manage 画面を開いたものです。

Tags: , , ,

CORE

.NET 6.0 ASP.NET Identity に MySQL 使用 (CORE)

by WebSurfer 2021年11月27日 13:53

先の記事「ASP.NET Identity で MySQL 利用 (CORE)」に、ASP.NET Core 3.1 MVC アプリで ASP.NET Identity のユーザー情報のストアに MySQL を利用するにはどうするかということを書きましたが、その Visual Studio 2022 + .NET 6.0 版です。

先の記事と違うのは、Visual Studio Community 2022 のテンプレートを使って .NET 6.0 でプロジェクトを作ったところと、非推奨になった NuGet パッケージ MySql.Data.EntityFrameworkCore に代えて Pomelo.EntityFrameworkCore.MySql を使ったところです。

先の記事で使った MySql.Data.EntityFrameworkCore は非推奨になったので、まずその代替えの Oracle 製 MySql.EntityFrameworkCore を使おうと思いましたが、この記事を書いた時点での最新バージョンが 5.0.8 で .NET 6.0 には対応してなさそうです。6.0.0-preview3.1 というのがありましたがプレビュー版ですし、依存関係が net5.0 と書いてあったので使うのは止めました。(一応 5.0.8 を試してみましたが Add-Migration に失敗します。さらに後日 6.0.1 も試しましたがやはり Add-Migration に失敗します)

Oracle は Entity Framework 対応は積極的ではなさそうな感じです。一方、Pomelo.EntityFrameworkCore.MySql はこの記事を書いた 2021/11/27 時点でバージョン 6.0.0 がすでにリリースされていましたので、この記事ではそれを使ってみました。

結果、Pomelo.EntityFrameworkCore.MySql バージョン 6.0.0 で一切支障なく ASP.NET Identity 用の MySQL データベースを構築できました。Oracle にはあまり期待しない方が良いのかも。

(1) プロジェクトの作成

Visual Studio 2022 のテンプレートを利用して .NET 6.0 の ASP.NET MVC アプリを作成します。「追加情報」の設定で[認証の種類(a)]は必ず「なし」としてください。

新しいプロジェクトの作成

(2) ASP.NET Core Identity の実装

ASP.NET Core Identity はスキャフォールディング機能を使って実装しますが、その前に、NuGet で Microsoft.VisualStudio.Web.CodeGeneration.Design をインストールします。

Web.CodeGeneration.Design

その後で Microsoft のドキュメント「ASP.NET Core プロジェクトでの Identity のスキャフォールディング」を参考に ASP.NET Core Identity を実装します。

ID の追加

レイアウトページはステップ (1) で生成したプロジェクトのレイアウトページ ~/Views/Shared/_Layout.cshtml を設定します。

ASP.NET Core Identity 関係のすべてのファイルを取り込むため[すべてのファイルをオーバーライド]にチェックを入れます。

コンテキストクラス名、エンティティクラス名は任意ですが、この記事では ApplicationDbContext, ApplicationUser としました。 何故かデザイナの + ボタンをクリックすると現れるダイアログのテキストボックス内で名前を設定しないとダメなので注意してください。また、エンティティクラス名を設定する際、コンテキストクラス名と同じ名前空間を追加しないと、コンテキストクラスと異なる名前空間になり、後で面倒なことになるので注意してください。

その後、追加した ASP.NET Core Identity 関係の Razor ページが働くよう、以下の追加・修正を行います。Visual Studio 2022 + .NET 6.0 で作ったプロジェクトでは Stratup.cs は無くなっていますので注意してください。サービス、ミドルウェア追加のためのコードは Program.cs に移すことにしたらしいです。

  1. Program.cs に builder.Services.AddRazorPages(); を追記。
  2. Program.cs の app.MapControllerRoute(name: "default", ... ); を書き換えて endpoints.MapRazorPages(); を追加。(これが無いと Razor ページのルーティングが働かないので必須)
  3. Areas/Identity/Page/Account/Manage/ の _Layout.cshtml で Layout = "/Views/Shared/_Layout.cshtml"; に変更。
  4. Views/Shared/_Layout.cshtml に <partial name="_LoginPartial" /> を追加。

(3) Pomelo.EntityFrameworkCore.MySql

NuGet で Pomelo.EntityFrameworkCore.MySql バージョン 6.0.0 をインストールします。

Pomelo.EntityFrameworkCore.MySql

先の記事で使った MySql.Data.EntityFrameworkCore は非推奨になってました。 代替えパッケージが MySql.EntityFrameworkCore とのことですので、まずそれの最新リリース版 5.0.8 を試してみたのですが、Add-Migration で以下のエラーとなります。

"Method 'AppendIdentityWhereCondition' in type 'MySql.EntityFrameworkCore.MySQLUpdateSqlGenerator' from assembly 'MySql.EntityFrameworkCore, Version=5.0.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' does not have an implementation."

Pomelo.EntityFrameworkCore.MySql には上の画像の通りバージョン 6.0.0 (.NET 6.0 用) がありますのでそれを使ってみたところ、Add-Migration, Update-Database で問題なくデーターベースを生成できました。

 

(4) 接続文字列の変更

テンプレートで自動生成された接続文字列は appsetteins.json にありますが、それは LocalDB を利用するように設定されていますので、MySQL に接続するように変更します。以下の例を見てください。

接続文字列の変更

例えば、上の画像のように database=coreidentity2 とデータベース名を指定すると、Entity Framework Code First の機能を使って coreidentity2 という名前のデータベースを新たに生成し、そこに必要なテーブルを生成してくれます。

(5) Program.cs の修正

自動生成されれた Program.cs ファイルで、サービス登録のコードが SQL Server を使うように設定されていますが、これを MySQL を使うように変更します。以下のような感じです。

サービス登録の変更

Pomelo.EntityFrameworkCore.MySql を使う場合、UseMySQL ではなくて UseMySql であること、引数が異なることに注意してください。詳しくは Pomelo.EntityFrameworkCore.MySql の「2. Services Configuration」のコードを見てください。

(6) プロジェクトのリビルド

ここで一旦プロジェクトをリビルドします。リビルドには成功するはずですが、以下の通り警告が 6 つ出ると思います (現時点での話で将来改善されるかも)。

プロジェクトのビルド

上の 2 つは LoginWith2fa.cshtml.cs での using 句のダブり、残り 4 つは NULL 許容参照型がプロジェクト全体で有効化されているものの一部の .cshtml ファイルのソースコードがそれに対応してないことによります。そこを直してもう一度リビルドします。

(7) Add-Migration の実行

パッケージマネージャーコンソールから Add-Migration CreateIdentitySchema を実行します (CreateIdentitySchema という名前は任意です)。

Add-Migration を実行

上の画像で赤色で反転された文は MySql.EntityFrameworkCore バージョン 5.0.8 を使って失敗した結果のメッセージです。その下が Pomelo.EntityFrameworkCore.MySql バージョン 6.0.0 を使って成功した結果です。

Migrations と言う名前のフォルダとその中に xxxxx_CreateIdentitySchema.cs というファイルが生成されているはずですので確認してください。ファイル名の xxxxx は作成時のタイムスタンプ、CreateIdentitySchema は Add-Migration コマンドで指定した名前です。

(8) Update-Database の実行

次に Update-Database を実行し、Entity Framework Code First の機能を利用して MySQL にデータベース / テーブルを作成します。成功すると、以下のようにデータベースと、必要なテーブルが一式生成されます。coreidentity2 というデータベース名は、上のステップ (4) で接続文字列に指定したものになります。

MySQL データベース

先の記事で問題となった"Specified key was too long; max key length is 3072 bytes" という制約のためエラーになるということはなかったです。

データベース / テーブルは CreateIdentitySchema.cs ファイルのコードに基づいて生成されるのですが、先の記事では主キーの長さが指定されてなかったところが、以下のように varchar(255) に指定されています。

CreateIdentitySchema.cs

utf8mb4 を使用していますので、主キーに設定された varchar(255) は 255 x 4 = 1,020 バイトになります。連結主キーでも制限の 3,072 より小さいので問題ないということのようです。

その後で Visual Studio から MVC アプリを起動しユーザー登録できます。登録したユーザーは上の手順で作成した MySQL データーベースに反映され、登録した ID とパスワードでアプリにログインできるようになります。

Tags: , , ,

CORE

ASP.NET Identity で MySQL 利用 (CORE)

by WebSurfer 2020年5月14日 17:33

Core 3.1 ベース(.NET Framework ではありません)の ASP.NET MVC アプリで認証に ASP.NET Core Identity を用い、ユーザー情報のストアに MySQL を利用するにはどうするかということを書きます。

Visual Studio 2022 + .NET 6.0 の ASP.NET Core Identity の場合は「.NET 6.0 ASP.NET Identity に MySQL 使用 (CORE)」を見てください。

.NET Framework 版の ASP.NET Identity の場合は「ASP.NET Identity で MySQL 利用 (.NET 版)」を見てください。

ネットの情報ではサードパーティ製の Pomelo.EntityFrameworkCore.MySql を使ったという記事を目にしますが、ここでは NuGet でインストールできる Oracle 製の MySql.Data.EntityFrameworkCore v8.0.20 を使ってみました。

Oracle 製の MySql.Data.EntityFrameworkCore は Core に対応してないので下記ステップ「(6) プロジェクトのビルド」でエラーになったという話を聞きましたが、最新版ではそのあたりは対応されているようです。

ただし、何も問題がなかったわけではなく、最後に Update-Database でデータベース / テーブルを生成するところで "Specified key was too long; max key length is 3072 bytes" というエラーが出ます・・・が、解決は可能でした。詳しくは下のステップ「(8) Update-Database の実行」を見てください。

(1) プロジェクトの作成

Visual Studio 2019 のテンプレートを利用して ASP.NET Core 3.1 MVC アプリを作成します。認証は「認証なし」のままとしておきます。

新しい ASP.NET Core Web アプリケーションの作成

認証に「個別のユーザーアカウント」を選んでプロジェクト作成時点から ASP.NET Identity を実装しても、それを MySQL を利用するように変更できると思います。しかし、そうすると Login, Register 他の認証関係の機能は Razor Class Library (RCL) として提供され、ソースコードはプロジェクトには含まれません。

認証関係のソースコードを見たい / 修正したいことがあるでしょうから(少なくとも登録、ログインページは書き換えたくなるはず)、まず「認証なし」で作って下のステップ (2) に述べるようにスキャフォールディング機能を利用して ASP.NET Identity を実装するのがよさそうです。(「個別のユーザーアカウント」で作って、特定のページをオーバーライドすることもできるそうですが)

(2) ASP.NET Core Identity の実装

Microsoft のドキュメント Scaffold identity into an MVC project without existing authorization を参考に、スキャフォールディング機能を利用して ASP.NET Identity を実装します。

ドキュメントの通り、ソリューションエクスプローラーでプロジェクトを右クリック⇒[追加(D)]⇒[新しいスキャフォールディングアイテム(F)...]で下の画像のダイアログが開きます。

新規スキャフォールディングアイテムの追加

上のダイアログで[インストール済み]の項目から[ID]を選択し、[追加]をクリックすると以下の画像の「ID の追加」ダイアログが表示されます。

ID の追加

レイアウトページ欄にはステップ (1) で生成したプロジェクトのレイアウトページ ~/Views/Shared/_Layout.cshtml を設定します。

ソースコードが必要なファイルに[オーバーライドするファイルの選択]でチェックを入れます。(上の画像では[すべてのファイルをオーバーライド]にチェックを入れて全てのファイルを選択しています。どれを選んだらよいか分からなかったので)

[データコンテキストクラス(D)]には、+ をクリックすると表示されるデフォルトをそのまま設定しました。必要なら任意の名前に変更できます。デフォルトでは xxxxxContext の xxxxx がプロジェクト名になり、プロジェクトルート下に Areas/Identity/Data というフォルダが作られ、その中にコンテキストクラスを含むファイル xxxxxContext.cs が生成されます。

[ユーザークラス(U)]にも同様に、+ をクリックすると表示されるデフォルトをそのまま設定しました。これも任意の名前に変更できます。デフォルトでは IdentityUser を継承した xxxxxUser クラスが生成され、xxxxx がプロジェクト名になります。

[ユーザークラス(U)]に何も設定せず空白のままにしておくと IdentityUser がそのまま使われます。基本的な機能はそれで問題ないですが、もし、将来プロファイル情報を追加するようなことがあると困ることになりますので、設定しておいた方がよさそうです。

その他、NuGet での Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore の追加、Razor ページを有効にするための Startup.cs へのコードの追加を忘れないようにしてください。詳しくは上に紹介した Microsoft のドキュメントを見てください。

(3) MySql.Data.EntityFrameworkCore

NuGet で MySql.Data.EntityFrameworkCore をインストールします。この記事を書いた時点では v8.0.20 しか見つからなかったのでそれをインストールしました。

2021/11/26 追記: MySql.Data.EntityFrameworkCore はいつの間にか非推奨になってました。 代替えパッケージが MySql.EntityFrameworkCore とのことです。それを使って同様なことができるかは未検証・未確認です。

MySql.Data.EntityFrameworkCore

関連するパッケージの更新・インスト���ルが自動的に行われます。その内容は以下の画像を見てください。

変更のプレビュー

(4) 接続文字列の変更

テンプレートで自動生成された接続文字列は appsetteins.json にありますが、それは LocalDB を利用するように設定されていますので MySQL に接続するように変更します。以下のような感じです。

接続文字列の変更

例えば、上の画像の database=coreidentity というようにデータベース名を指定すると、Entity Framework Code First の機能を使って coreidentity という名前のデータベースを新たに生成し、そこに必要なテーブルを生成してくれます。(データベース名は任意に設定できます。この記事で coreidentity としたのは単なる例です)

(5) IdentityHostingStartup.cs の修正

自動生成されれた Areas/Identity/IdentityHostingStartup.cs ファイルで、サービス登録のコードが SQL Server を使うように設定されていますが、これを MySQL を使うように変更します。以下のような感じです。

サービス登録の変更

なお、IdentityHostingStartup.cs ファイルは、上のステップ (2) のようにスキャフォールディング機能を利用して ASP.NET Identity を実装した場合に生成されるものです。プロジェクト作成の時点で認証を「個別のユーザーアカウント」とした場合は、サービス登録のコードは Startup.cs ファイルに含まれますので注意してください。

(6) プロジェクトのビルド

ここで一旦プロジェクトをビルドしてみました。以下の通り成功します。

プロジェクトのビルド

参考にさせていただいた記事「ASP.NET CoreでMySQLを利用する」ではここでエラーとなったそうです。

その記事では Core のバージョンは 2.0、MySql.Data.EntityFrameworkCore のバージョンは 8.0.6 だったそうです。この記事では Core は 3.1、MySql.Data.EntityFrameworkCore は 8.0.20 です。その差があるのでしょうか。

(7) Add-Migration の実行

パッケージマネージャーコンソールから Add-Migration CreateIdentitySchema を実行します(CreateIdentitySchema という名前は任意です。また、Core では Enable-Migration は不要になったそうです)。

Add-Migration を実行

Migrations フォルダには CreateIdentitySchema.cs ファイルが生成されます。ざっと見たところ内容は正しそうです。(ツールのバージョンが 3.1.2 でランタイムのバージョン 3.1.4 より古いという警告は出ていますが Migration には影響ないようです)

(8) Update-Database の実行

次に Update-Database を実行し、Entity Framework Code First の機能を利用して MySQL にデータベース / テーブルの生成を試みます・・・が、以下の画像の通りダメでした。

Update-Database 実行結果

メッセージを見ると AspNetUserRoles というテーブルを生成する際に "Specified key was too long; max key length is 3072 bytes" という制約のためエラーになったということのようです。

以下、少々話が長くなりますが、なぜそういうエラーになるかと、その解決方法を書きます。

データベース / テーブルは CreateIdentitySchema.cs ファイルのコードに基づいて生成されるのですが、主キーは全て、

UserId = table.Column<string>(nullable: false)

というというような maxLength が指定されない設定となります。その場合、上の画像にある通り、テーブルを生成する create 句では主キーは varchar(767) に設定されます。

varchar(767) の 767 という数字は MySQL の主キーに許容される最大バイト数で、それゆえ主キーに maxLength が指定されないと varchar(767) になるのだと思われます。

767 バイトという制限は、「InnoDBインデックスの最大キー長について」という記事によると、ある条件で 3,072 バイトまで拡張できるそうで、MySQL 5.7 以降がその条件に当てはまるそうです。この記事では MySQL 8.x を使っているのでエラーメッセージにある通り 3,072 バイトが上限になっているのだと思います。

何故 nvarchar ではなくて varchar になるのか不思議でしたが、MySQL のドキュメント 10.3.7 The National Character Set によると、"MySQL uses utf8 as this predefined character set" なのでどちらでも同じなのだそうです。ちなみに create 句で nvarchar と指定しても、生成されるのは varchar になるそうです。

この記事で使用している MySQL 8.0.19 で使用されている文字コードを確認してみましたが、以下のようになっていました。

使用されている文字コード

utf8mb4 というのは、10.1.10.7 utf8mb4 文字セット (4 バイトの UTF-8 Unicode エンコーディング) によると、"utf8 という名前の文字セットは、文字あたり最大 3 バイトを使用し、BMP 文字だけを含みます。utf8mb4 文字セットは、文字ごとに最大 4 バイトを使用し、補助文字をサポートします" ということだそうです。

utf8mb4 を使用していますので、主キーに設定された varchar(767) は 767 x 4 = 3,068 バイトになります。制限の 3,072 より小さいので単独の主キーなら varchar(767) で問題ないはずです。

しかし、ASP.NET Core Identity が使うテーブルには連結主キーが設定されるものがあり、それが最大 3,072 バイトの制約を超えるため "Specified key was too long; max key length is 3072 bytes" というエラーになったということのようです。

連結主キーが設定されるテーブルは AspNetUserRoles と AspNetUserTokens です。

それらのテーブルの主キーが varchar(767) とならないよう、CreateIdentitySchema.cs ファイルの当該コードに制限 maxLength: 128 を設定してやります。以下の画像の赤枠部分を見てください。

maxLength: 128 を設定

Id フィールドには d85de5ae-a926-45cd-831a-4835034f6b79 というように書式指定された Guid の文字列が設定されますので、varchar(128) で十分なはずです(少なくとも現時点では)。

上の画像のように maxLength: 128 を設定後 Update-Database を実行すれば MySQL に ASP.NET Core Identity に必要なデータベースとテーブルが生成されます。

その後で Visual Studio から MVC アプリを動かしてユーザー登録できます。登録したユーザーはデーターベースに反映されます。もちろん登録した ID とパスワードでアプリにログインできるようになります。

Tags: , , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar