マイグレーションの時に、列の文字数長さの設定でmaxの部分でエラーになるので、それぞれにどんな情報が入っていて、何を設定すべきか調べてみた。
Identityで生成されるテーブルとそれらの関係は以下のとおり

7つのテーブルがあり、Userとそれに関連するテーブルが4つと
Roleとそれに関するテーブルが2つと
UserとRoleを結ぶテーブルが1つの計7つで構成されている
AspNetUsersテーブル
AspNetUserテーブルは、ユーザーに関する主要な情報が格納
列名 | nvarchar(max) | 内容 |
---|---|---|
Id | ユーザーの一意の識別子。通常はGUID(ハイフンあり) | |
UserName | ユーザーのログイン名 | |
NormalizedUserName | 検索などの比較で効率的に行うための正規化(大文字) | |
メールアドレス | ||
NormalizedEmail | 検索などの比較で効率的に行うための正規化(大文字) | |
EmailConfirmed | メールアドレスによる確認ができたかを示すブール値 | |
PasswordHash | 〇 | ユーザーパスワード(Hash値) |
SecurityStamp | 〇 | セキュリティ目的で使用される一意の値 |
ConcurrencyStamp | 〇 | 同時実行制御に使用。GUIDが使われる |
PhoneNumber | 〇 | 電話番号 |
PhoneNumberConfirmed | 電話番号による確認ができたかを示すブール値 | |
TwoFactorEnabled | 二要素認証が有効かどうかを示すブール値 | |
LockoutEnd | アカウントロックアウトが終了する日時 | |
LockoutEnabled | アカウントのロックアウトが有効かどうかのブール値 | |
AccessFailedCount | ログイン失敗回数 |
・AIの見解
PasswordHash・・・一般的なハッシュアルゴリズム(例:SHA256)の出力は64文字程度です。将来的なハッシュアルゴリズムの変更に対応できる余裕を持たせて128文字程度が妥当ではないか
SecurityStamp・・・セキュリティスタンプはGUIDベースで生成されることが多いです。GUIDの文字列表現は通常36文字です。よって36文字
ConcurrencyStamp・・・同時実行制御に使用されるタイムスタンプです。通常GUIDが使用される。GUIDの文字列表現は通常36文字。よって36文字
PhoneNumber・・・国際電話番号を考慮すると15桁程度。中継電話会社経由の番号だと16桁になることもある。電話番号の桁数はいつかわってもおかしくないので多少余裕をもたせるとよさそう。よって20文字
AspNetUserClaimsテーブル
AspNetUserClaimsテーブルは、ーザーに関連付けられたクレーム情報が格納
列名 | nvarchar(max) | 内容 |
---|---|---|
Id | プライマリキーとして機能する一意の識別子 | |
UserId | クレームを設定するUserId | |
ClaimType | 〇 | クレームの種類や名前 |
ClaimValue | 〇 | クレームの値 |
クレームは、ユーザーはロールといった概念のほかに情報を追加し細かい認証の制御を行うために使用する
よって、クレームの種類や値を設定するのは開発者次第のためお好きな文字数を設定すればよい
長い名称を使うことなければ64文字とかで十分かなと
AspNetUserLoginsテーブル
AspNetUserLoginsテーブルは、外部認証プロバイダーを使用してログインしたユーザーの情報が格納
列名 | nvarchar(max) | 内容 |
---|---|---|
LoginProvider | 外部認証プロバイダーの名前(例:Google、Facebook、Microsoft等) | |
ProviderKey | 認証プロバイダーがユーザーに割り当てた一意の識別子 | |
ProviderDisplayName | 〇 | 認証プロバイダーの表示名を格納 |
UserId | 該当するUserId |
ProviderDisplayNameは、例えばGoogleの認証だとGoogleが格納されています。そこまで長い名前は入るとおもえないので、64文字程度もあれば十分かなと
AspNetUserTokensテーブル
AspNetUserTokensテーブルは、ユーザーに関連する各種トークン情報が格納
列名 | nvarchar(max) | 内容 |
---|---|---|
UserId | AspNetUsersテーブルのIdに対応する、ユーザーの一意の識別子 | |
LoginProvider | トークンを生成したプロバイダーの名前を指定 | |
Name | トークンの名前や種類を格納 | |
Value | 〇 | トークンの実際の値を格納 |
どういうときにつかうのか?
パスワードリセット、メール確認、二要素認証、外部認証プロバイダー、リフレッシュトークン、カスタムトークンなどだそうです
AIの見解:
OAuth 2.0のアクセストークンは通常200〜400文字程度
JWTベースのトークンは500〜1000文字程度になることがあります
リフレッシュトークンは通常、アクセストークンよりも長くなる傾向があります
トークンのサイズが将来的に大きくなる可能性を考慮する必要があります
よって2000文字程度の長さが妥当では?
とのこと。
AspNetUserRolesテーブル
AspNetUserRolesテーブルは、ユーザーとロールの関連付けに関する情報が格納
列名 | nvarchar(max) | 内容 |
---|---|---|
UserId | UserIdを設定 | |
RoleId | RoleIdを設定 |
AspNetRolesテーブル
AspNetRolesテーブルは、アプリケーション内のロールに関する情報が格納
列名 | nvarchar(max) | 内容 |
---|---|---|
Id | UserIdを設定 | |
Name | RoleIdを設定 | |
NormalizedName | 検索などの比較で効率的に行うための正規化(大文字) | |
ConcurrencyStamp | 〇 | 同時実行制御に使用。GUIDが使われる |
・AIの見解
ConcurrencyStamp・・・同時実行制御に使用されるタイムスタンプです。通常GUIDが使用される。GUIDの文字列表現は通常36文字。よって36文字
AspNetRoleClaimsテーブル
AspNetRoleClaimsテーブルは、ロールに関連付けられた追加の情報(クレーム)が格納
AspNetUserClaimsのRole版
列名 | nvarchar(max) | 内容 |
---|---|---|
Id | プライマリキーとして機能する一意の識別子 | |
RoleId | クレームを設定するRoleId | |
ClaimType | 〇 | クレームの種類や名前 |
ClaimValue | 〇 | クレームの値 |
クレームは、ユーザーはロールといった概念のほかに情報を追加し細かい認証の制御を行うために使用する
よって、クレームの種類や値を設定するのは開発者次第のためお好きな文字数を設定すればよい
長い名称を使うことなければ64文字とかで十分かなと
同時実行制御について
同じレコードを複数のリクエストにより変更を行った際に、どちらのリクエストで変更したのか、判断するために、ConcurrencyStampにGUIDを設定し判断に使っています。
- Selectで対象のレコードの情報を取得する
- 新しいGUIDを取得する
- 対象レコードを取得する際に、1で取得したConcurrencyStampも条件に含めレコードをしぼり更新を行う。その際に新しいGUIDを設定する
これにより、同時実行した場合、更新ができれば自分のリクエストにより更新ができたことになり
更新ができない場合(他のリクエストによりすでにConcurrencyStampの値が変わっていた場合)は更新が失敗することになります