Contents

使用 .Net Core Identity 實作網頁登入登出

這邊重零開始建置 Net Core Identity。

步驟

1. Net Core Identity 設定

GIT可參考下面

  1. 資料庫設定 · malagege/NetCoreAuthSample@bcce6fc
  2. Identity.EFCore 設定 · malagege/NetCoreAuthSample@211ca25

安裝基本元件

1
2
3
4
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.17" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.17" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.17" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.17" />

注意DbContext繼承要調整 IdentityDbContext

1
2
3
4
5
6
7
    public class AppDbContext : IdentityDbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {

        }
    }

Startup.cs

1
2
           services.AddIdentity<IdentityUser, IdentityRole>()
                    .AddEntityFrameworkStores<AppDbContext>();

剩下看GIT。

2. Migration DB

1
Add-Migration AddingIdentity

會自動產生
參考: NetCoreAuthSample/20220811093637_AddingIdentity.Designer.cs at 0fad9d029b4097257e365ded0c7727058a3e81ad · malagege/NetCoreAuthSample

3. 註冊帳號頁面處理

GIT:註冊帳號 · malagege/NetCoreAuthSample@0fad9d0

新增檔案就不特別寫,都在GIT上。
要了解的是

  1. SignInManager 可以做登入/登出動作
  2. UserManager 可以新增帳號動作

4. 註冊密碼檢核設定

GIT: 註冊密碼檢核設定 · malagege/NetCoreAuthSample@a70bc35

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
            services.Configure<IdentityOptions>(options =>
            {
                // 密碼最小長度  (預設值:6)
                options.Password.RequiredLength = 6;
                // 密碼中允許最大重複字符數 (ex: "aaa123" ,"abbb123")  axabac 會過
                options.Password.RequiredUniqueChars = 3;
                // 至少使用非字母數字字符 (預設值: true)
                options.Password.RequireNonAlphanumeric = false;
                // 密碼是否包含小寫 (預設值: true)
                options.Password.RequireLowercase = false;
                // 密碼是否包含大寫 (預設值: true)
                options.Password.RequireUppercase = false;
            });

選上下方法其中一個

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
            services.AddIdentity<IdentityUser, IdentityRole>(options =>
            {
                // 密碼最小長度  (預設值:6)
                options.Password.RequiredLength = 6;
                // 密碼中允許最大重複字符數 (ex: "aaa123" ,"abbb123")  axabac 會過
                options.Password.RequiredUniqueChars = 3;
                // 至少使用非字母數字字符 (預設值: true)
                options.Password.RequireNonAlphanumeric = false;
                // 密碼是否包含小寫 (預設值: true)
                options.Password.RequireLowercase = false;
                // 密碼是否包含大寫 (預設值: true)
                options.Password.RequireUppercase = false;
            });)

這邊可以設定有

  1. UserOptions
  2. SignInOptions
  3. LockoutOptions
  4. TokenOptions
  5. StoreOptions
  6. ClaimsIdentityOptions

5. 自訂錯誤訊息

GIT:自訂義錯誤訊息 · malagege/NetCoreAuthSample@b1203f6

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public class CustomIdentityErrorDescriber : IdentityErrorDescriber
    {
        public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"未知錯誤!" }; }
        public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "並發錯誤,對象已被修改!" }; }
        public override IdentityError PasswordMismatch() { return new IdentityError { Code = "Password", Description = "密碼錯誤!" }; }
        public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "無效 token." }; }
        public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "當前用戶已經登錄!" }; }
        public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = "UserName", Description = $"用戶名 '{userName}' 錯誤,只可以包含數字和字母!" }; }
        public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = "Email", Description = $"信箱 '{email}' 格式錯誤!" }; }
        public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = "UserName", Description = $"帳號 '{userName}' 已存在!" }; }
        public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = "Email", Description = $"信箱 '{email}' 已經存在!" }; }
        public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"角色 '{role}' 驗證錯誤!" }; }
        public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"角色名 '{role}' 已經存在!" }; }
        public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "此帳號設定密碼了" }; }
        public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "此帳號未鎖定" }; }
        public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"使用者已關聯角色 '{role}'." }; }
        public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"使用者沒有關聯角色  '{role}'." }; }
        public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = "Password", Description = $"密碼至少 {length} 位!" }; }
        public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = "Password", Description = "密碼必須至少有一個非字母數字字符." }; }
        public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = "Password", Description = "密碼至少有一個數字 ('0'-'9')." }; }
        public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = "Password", Description = "密碼必須包含小寫字母 ('a'-'z')." }; }
        public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = "Password", Description = "密碼必須包含大寫字母 ('A'-'Z')." }; }
    }

插入這一行.AddErrorDescriber<CustomIdentityErrorDescriber>(),如下面。

1
2
3
            services.AddIdentity<IdentityUser, IdentityRole>()
                    .AddErrorDescriber<CustomIdentityErrorDescriber>()
                    .AddEntityFrameworkStores<AppDbContext>();

6. View 判斷是否登入

View 顯示帳號是否登入方法 · malagege/NetCoreAuthSample@43c6275

7. 帳號登入與登出功能

這段沒有加入,登入功能無法正常,你會發現你登入都遇到失敗。結果是少這兩行,正確來說app.UseAuthentication();就可以解決。不過後續我要做登入權限設定,所以先加。

1
2
3
4
            // 當帳號沒有檢查到登入資料,請確認這兩個是否加入 Middleware
            app.UseAuthentication();

            app.UseAuthorization();

重點知識

UserManager,SignInManager

UserManager

控制帳號CRUD方法

  1. CreateAsync
  2. DeleteAsync
  3. UpdateAsync

SignInManager

登入/登出判斷

  1. SignInAsync
  2. SignOutAsync
  3. IsSignIn

記住密碼 Cookies

http://localhost:50000/

https://i.imgur.com/VG3M7Xo.png

關掉瀏覽器重開需要再做登入。
有點選記住密碼,下次打開登入狀態會存在。

https://i.imgur.com/df63lFL.png

感想

Net Core Identity 設定非常簡單,連帳號管理方式和驗證方式都幫你處理好了,你不必自己手寫,可以專心在別的設計上。目前我看過 Spring Boot和 Laravel 帳號管理方式,我覺得這個是最簡單的。這只是開頭,後續計入相關東西。

相關文章

[MVC] 實作客製化的identity | 朕在coding - 點部落