.NET Core與Vue3登入者和角色授權管理功能模組(用js版本,cors+Identity+Jwt)_中文內容亂碼異常排除_增加導覽列_註冊與登入


刪除預設的vue介面程式檔案



調整App.vue的部分

1
2
3
4
5
6
7
<script setup>
import Home from './components/Home.vue'
</script>

<template>
  <Home />
</template>

預設導入Home元件


修改main.js
main.css取消引入,此自訂樣式目前我們不需使用到。

會發現中文內容運行起來出現亂碼異常

可將App.vue 跟 Home.vue (未來你各個元件都做此作業)


選編碼另存 將預設Big5改為UTF8



重新運行起來即可正常


在./src/components目錄下增加
NavBar.vue

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<template>
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid ms-3 me-3">
            <router-link class="navbar-brand" to="/">管理系統</router-link>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNavDropdown">
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <router-link class="nav-link active" aria-current="page" to="/">首頁</router-link>
                    </li>
                    <li class="nav-item" v-if="isAdmin">
                        <router-link class="nav-link" to="/manage/user">使用者管理</router-link>
                    </li>
                    <li class="nav-item" v-if="isAdmin">
                        <router-link class="nav-link" to="/manage/role">角色管理</router-link>
                    </li>
                </ul>
            </div>
            <div class="d-flex">
                <ul class="navbar-nav" v-if="!isLogin">
                    <li class="nav-item">
                        <router-link class="nav-link" to="/register">註冊</router-link>
                    </li>
                    <li class="nav-item">
                        <router-link class="nav-link" to="/login">登入</router-link>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</template>

調整App.vue 替換改引入它





測試運行起來


增加Router render部分
可以透過<router-view>實踐路由渲染
於App.vue中 加入<router-view>元素
如此一來即可實踐版面布局中子頁鑲嵌進來統一布局的部分了



因為在src/router.js中有配置了根路徑 (/) 訪問到對應元件為 Home.vue元件


在index.html中可以調整title 改顯示我們指定的





後端web api專案目錄增加 Models目錄
並加入AppUser.cs的類別

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
using Microsoft.AspNetCore.Identity;

namespace Vue.NET.Identity.Auth.Models
{
    public class AppUser : IdentityUser
    {
        //姓名
        public string? FullName { get; set; }
        
        //大頭照
        public string? Avatar { get; set; }
    }
}

加入AppRole.cs的類別

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
using Microsoft.AspNetCore.Identity;

namespace Vue.NET.Identity.Auth.Models
{
    public class AppRole : IdentityRole
    {
        //啟用與否
        public bool IsEnabled { get; set; }  
    }
}


進行ASP.NET Core Identity EFCore ORM資料操作相關資料庫配置
添加編寫DbContext子類別
於專案根目錄增加
AppDbContext.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Vue.NET.Identity.Auth.Models;

namespace Vue.NET.Identity.Auth
{
    //繼承IdentityDbContext (為Identity框架中用的DbContext)
    //這邊我們整套應用都會只統一使用單一個DbContext也就是此AppDbContext
    //IdentityDbContext<T1,T2,T3>各自泛型代表
    //AppUser:使用者帳號延伸欄位model定義,若無延伸就改用預設的IdentityUser
    //AppRole:使用者帳號角色延伸欄位model定義,若無延伸就改用預設的IdentityRole。
    //string:代表使用者帳號table和Role Table的PK類型,這邊兩者必須用相同的PK DataType,現階段都為string。
    public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {

        }
    }
}

配置資料庫連線字串 WooBetterConnection

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "WooBetterConnection": "Server=.\\SQLEXPRESS;Database=WooSysDb;Trusted_Connection=True;TrustServerCertificate=true;MultipleActiveResultSets=true;User ID=admin;Password=rootroot"
  }
}

開啟Program.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Vue.NET.Identity.Auth.Models;
using Vue.NET.Identity.Auth;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(builder =>
    {
        builder.WithOrigins("http://localhost:5173").AllowAnyHeader();
    });
});

//註冊AppDbContext
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("WooBetterConnection")), contextLifetime: ServiceLifetime.Singleton);
//註冊Identity服務,並指定使用者和角色物件。
builder.Services.AddIdentity<AppUser, AppRole>(options => options.SignIn.RequireConfirmedAccount = false).AddEntityFrameworkStores<AppDbContext>().AddDefaultTokenProviders();
//配置Identity密碼規範
builder.Services.Configure<IdentityOptions>(options =>
{
    //密碼中需要有一個(0-9)之間的數字。
    options.Password.RequireDigit = false;
    //密碼中需要有小寫字符。
    options.Password.RequireLowercase = false;
    //密碼中需要有非字母數字字符。
    options.Password.RequireNonAlphanumeric = false;
    //密碼中需要有大寫字符。
    options.Password.RequireUppercase = false;
    //密碼的最小長度。
    options.Password.RequiredLength = 6;
    //密碼中需要有非重覆字符數。
    options.Password.RequiredUniqueChars = 1;
});


builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseCors();
app.UseAuthorization();

app.MapControllers();

app.Run();

在var app = builder.Build(); 和if (app.Environment.IsDevelopment())兩句之間
來做只有第一次的配置(只運行一次的配置)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//生成資料庫和table結構
var scope = app.Services.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
//如果資料庫不存在,就生成table結構
var r = context.Database.EnsureCreated();
if (r)
{
    //獲取user和role manager。
    var userManager = scope.ServiceProvider.GetRequiredService<UserManager<AppUser>>();
    var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<AppRole>>();

    //添加admin user
    var adminUser = new AppUser() { Id = Guid.NewGuid().ToString(), UserName = "admin", Email = "chousml@gmail.com", EmailConfirmed = true, };
    await userManager.CreateAsync(adminUser, "admin12345678");

    //添加admin role group
    var adminRole = new AppRole() { Name = "Admin", IsEnabled = true };
    await roleManager.CreateAsync(adminRole);

    //將admin user 添加至admin role group
    await userManager.AddToRolesAsync(adminUser, new string[] { adminRole.Name });
    userManager.Dispose();
    roleManager.Dispose();
}

運行web api專案後即可看到DB成功migrate並產生資料



註冊(添加user)

[前端部分]
於vue專案
在/src/components目錄下產生UserRegister.vue元件(註冊頁面的元件)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
    <div class="shadow-sm p-3 m-5 bg-body-tertiary row rounded">
        <div class="col">
            <img width="600" class="rounded" src="../assets/First.png" />
        </div>
        <div class="col">
            <h1 class="mb-5"><span class="text-primary">註冊</span> 後台管理</h1>

            <div class="mt-3">
                <input type="text" v-model="userName" placeholder="請輸入帳號" class="form-control w-75" />
            </div>
            <div class="mt-3">
                <input type="password" v-model="userPwd" placeholder="請輸入密碼" class="form-control w-75" />
            </div>
            <div class="mt-3">
                <input type="email" v-model="userEmail" placeholder="請輸入Email" class="form-control w-75" />
            </div>
            <div class="form-check mt-3">
                <input class="form-check-input" v-model="isAccept" type="checkbox" value="true" id="flexCheckDefault">
                <label class="form-check-label small" for="flexCheckDefault">
                    閱讀並同意
                </label>
            </div>
            <div class="d-grid gap-2 mt-3">
                <button class="btn btn-primary btn-lg w-75" @click="save" type="button">註冊</button>
            </div>
        </div>
    </div>
</template>


於vue專案
在/src/router.js中添加相應路由配置(如此使用者就可透過/register訪問到對應註冊頁面元件)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
    history: createWebHistory(), //html5 history
    routes: [
        {
            name: 'Home',
            path: '/',
            component: () => import('@/components/Home.vue'),
            meta: {
                title: '首頁'
            }
        },
        {
            name: 'UserRegister',
            path: '/register',
            component: () => import('@/components/UserRegister.vue'),
            meta: {
                title: '帳號註冊'
            }
        }
    ]
})
export default router;


[後端部分]
加入一個對應ViewModel class 於Models目錄下,名稱:UserViewModel.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using System.ComponentModel.DataAnnotations;

namespace Vue.NET.Identity.Auth.Models
{
    public class UserViewModel
    {
        //使用者帳號(名稱)
        [Required]
        public string? UserName { get; set; }

        //密碼
        [Required]
        public string? Password { get; set; }

        //郵件
        public string? Email { get; set; }
    }
}


增加對應後端web api控制器 ,名稱:AccountController.cs
依賴注入進來UserManager 和SignInManager進來
並撰寫給vue前端http post請求的UserRegister() method
[AllowAnonumouse]代表可匿名訪問不受權限管控。
EmailConfirmed 這邊自動先turn true不然還要處裡發信驗證,如此一來就能直接登入。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Vue.NET.Identity.Auth.Models;

namespace Vue.NET.Identity.Auth.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AccountController : ControllerBase
    {
        private readonly UserManager<AppUser> _userManager;
        private readonly SignInManager<AppUser> _signInManager;
        public AccountController(UserManager<AppUser> userManager,
                                 SignInManager<AppUser> signInManager)
        {
            _userManager = userManager;
            _signInManager = signInManager;
        }

        /// <summary>
        /// 註冊添加使用者帳號。
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("Register")]
        public async Task<IdentityResult> UserRegister(UserViewModel user)
        {
            if (string.IsNullOrWhiteSpace(user.Password)) return IdentityResult.Failed();
            
            var appUser = new AppUser { UserName = user.UserName, Email = user.Email, EmailConfirmed = true };
            //提交
            var result = await _userManager.CreateAsync(appUser, user.Password);
            return result;
        }





    }
}

這邊方法回傳型別是IdentityResult 於vue前端接收得到Failed 或Succeeded 來判斷成功與否。

可將web api運行在swag文檔中測試



那在資料庫中也有產生一筆User資料,這邊密碼預設有被hash過,無法逆轉編碼回來的。
因此若有遺失遺忘就只能修改密碼重置。

[前端部分]

這邊我們要來調整於vue頁面增加call api的js邏輯

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<template>
    <div class="shadow-sm p-3 m-5 bg-body-tertiary row rounded">
        <div class="col">
            <img width="600" height="700" class="rounded" src="../assets/First.avif" />
        </div>
        <div class="col">
            <h1 class="mb-5"><span class="text-primary">註冊</span> 後台管理</h1>
            <div v-show="isMsg" class="alert alert-warning w-75">
                {{msg}}
            </div>
            <div class="mt-3">
                <input type="text" v-model="userName" placeholder="請輸入帳號" class="form-control w-75" />
            </div>
            <div class="mt-3">
                <input type="password" v-model="userPwd" placeholder="請輸入密碼" class="form-control w-75" />
            </div>
            <div class="mt-3">
                <input type="email" v-model="userEmail" placeholder="請輸入Email" class="form-control w-75" />
            </div>
            <div class="form-check mt-3">
                <input class="form-check-input" v-model="isAccept" type="checkbox" value="true" id="flexCheckDefault">
                <label class="form-check-label small" for="flexCheckDefault">
                    閱讀並同意
                </label>
            </div>
            <div class="d-grid gap-2 mt-3">
                <button class="btn btn-primary btn-lg w-75" @click="save" type="button">註冊</button>
            </div>
        </div>
    </div>
</template>

<script setup>
    import { ref } from 'vue'
    import axios from "../axios"
    const userName = ref('');//用戶名
    const userPwd = ref('');//密碼
    const userEmail = ref('');//郵箱地址
    const isAccept = ref();//閱讀並同意
    //提示信息
    const msg = ref('');
    //提示信息是否顯示
    const isMsg = ref(false);
    //保存
    const save = () => {
        if (!isAccept.value) {
            isMsg.value = true;
            msg.value = "請閱讀並同意條款。";
            return;
        }
        //用戶名和密碼不為空。
        if (userName.value != '' && userPwd.value != '') {
            //關閉提示框
            isMsg.value = false;
            //發起HTTP請求
            axios({
                url: '/api/account/register',
                method: 'post',
                data: { userName: userName.value, password: userPwd.value, email: userEmail.value }
            }).then((res) => {
                const d = res.data;
                if (d.succeeded == true) {
                    isMsg.value = true;
                    msg.value = "您已成功註冊,請登入系統";
                }
                else {
                    isMsg.value = true;
                    msg.value = d.errors[0].description;
                }
            });
        } else {
            //顯示提示框
            isMsg.value = true;
            //提示信息
            msg.value = '帳號和密碼為必填。';
        }
    }
</script>


這樣就有相關的前端UI互動
比方沒勾選閱讀與同意


比方帳號密碼故意沒填


若發現後端API怎麼都沒trigger到就要檢查看看後端web api CORS配置對不對了





登入(authentication)頁面功能

[前端部分]


於vue專案
在/src/components目錄下產生UserLogin.vue元件(登入頁面的元件)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<template>
    <div class="shadow-sm p-3 m-5 bg-body-tertiary row rounded">
        <div class="col">
            <div class="image-container">
                <img class="rounded" src="../assets/First.avif" />
            </div>
        </div>
        <div class="col">
            <h1 class="mb-5"><span class="text-primary">登入</span> 後台管理</h1>
            <div v-show="isMsg" class="alert alert-warning w-75">
                {{msg}}
            </div>
            <div class="mt-3">
                <input type="text" v-model="userName" placeholder="請輸入帳號" class="form-control w-75" />
            </div>
            <div class="mt-3">
                <input type="password" v-model="userPwd" placeholder="請輸入密碼" class="form-control w-75" />
            </div>
            <div class="form-check mt-3">
                <input class="form-check-input" type="checkbox" value="true" v-model="isAccept" id="flexCheckDefault">
                <label class="form-check-label small" for="flexCheckDefault">
                    閱讀並同意
                </label>
            </div>
            <div class="d-grid gap-2 mt-3">
                <button class="btn btn-primary btn-lg w-75" @click="login" type="button">登入</button>
            </div>
        </div>
    </div>
</template>

<style>
    .image-container {
        display: flex;
        align-items: center;
        justify-content: center;
    }

        .image-container img {
            max-height: 100%;
            max-width: 100%;
            object-fit: contain;
        }
</style>

<script setup>
    import { ref } from 'vue'
    import axios from "../axios"
    import { useRouter } from 'vue-router'

    const router = useRouter();
    const userName = ref('');//用戶名
    const userPwd = ref('');//密碼
    const isAccept = ref();//是否同意條款
    const msg = ref('');//提示信息
    const isMsg = ref(false);//提示信息是否顯示
    const login = () => {
        if (!isAccept.value) {
            isMsg.value = true;
            msg.value = "請閱讀並同意條款。";
            return;
        }
        //帳號和密碼不為空。
        if (userName.value != '' && userPwd.value != '') {
            //關閉提示框
            isMsg.value = false;
            
            axios({
                url: '/api/account/login',
                method: 'post',
                data: { userName: userName.value, password: userPwd.value }
            }).then((res) => {
                try {
                    if (res.data) {
                        const d = res.data;
                        isMsg.value = true;
                        msg.value = "登入成功。";
                        localStorage.setItem('userName', userName.value);
                        localStorage.setItem('token', d.token);
                        localStorage.setItem('role', d.roleList);
                        localStorage.setItem('headImg', d.avatar);
                        router.push('/');//跳轉回首頁Home.vue
                    }
                } catch (error) {
                    isMsg.value = true;
                    msg.value = error;
                }
            });
        } else {
            //顯示提示框
            isMsg.value = true;
            //提示信息
            msg.value = '帳號和密碼為必填。';
        }
    }
</script>




於vue專案
在/src/router.js中添加相應路由配置(如此使用者就可透過/login訪問到對應登入頁面元件)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
    history: createWebHistory(), //html5 history
    routes: [
        {
            name: 'Home',
            path: '/',
            component: () => import('@/components/Home.vue'),
            meta: {
                title: '首頁'
            }
        },
        {
            name: 'UserRegister',
            path: '/register',
            component: () => import('@/components/UserRegister.vue'),
            meta: {
                title: '帳號註冊'
            }
        },
        {
            name: 'UserLogin',
            path: '/login',
            component: () => import('@/components/UserLogin.vue'),
            meta: {
                title: '登入'
            }
        }
    ]
})
export default router;



[後端部分]

添加UserLogin web api方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Vue.NET.Identity.Auth.Models;

namespace Vue.NET.Identity.Auth.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AccountController : ControllerBase
    {
        private readonly UserManager<AppUser> _userManager;
        private readonly SignInManager<AppUser> _signInManager;
        public AccountController(UserManager<AppUser> userManager,
                                 SignInManager<AppUser> signInManager)
        {
            _userManager = userManager;
            _signInManager = signInManager;
        }

        /// <summary>
        /// 註冊添加使用者帳號。
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("Register")]
        public async Task<IdentityResult> UserRegister(UserViewModel user)
        {
            if (string.IsNullOrWhiteSpace(user.Password)) return IdentityResult.Failed();
            
            var appUser = new AppUser { UserName = user.UserName, Email = user.Email, EmailConfirmed = true };
            //提交
            var result = await _userManager.CreateAsync(appUser, user.Password);
            return result;
        }

        private const string signingKey = "test1968196828825252";
        private const string issuer = "Samuel";
        private const string audience = "SamuelAPI";

        /// <summary>
        /// 使用者登入
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("Login")]
        public async Task<dynamic> UserLogin(UserViewModel user)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(user.UserName) || string.IsNullOrWhiteSpace(user.Password))
                    return NotFound();
                //Login 處理
                var result = await _signInManager.PasswordSignInAsync(user.UserName, user.Password, false, false);
                if (!result.Succeeded)
                    return BadRequest("帳號或密碼錯誤。");
                //By帳號名取得appUser
                var appUser = await _userManager.FindByNameAsync(user.UserName);
                if (appUser == null)
                    return NotFound();
                //取得登入帳號掛的對應角色清單
                var roleList = await _userManager.GetRolesAsync(appUser);
                var claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.Sid, appUser.Id));
                claims.Add(new Claim(ClaimTypes.Name, user.UserName));
                if (roleList.Count > 0)
                {
                    //分配權限給使用者帳號
                    foreach (var role in roleList)
                    {
                        claims.Add(new Claim(ClaimTypes.Role, role));
                    }
                }
                //配置密鑰
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey));
                //配置憑證
                var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                //產生 token
                var jwtToken = new JwtSecurityToken(issuer, audience, claims, expires: DateTime.UtcNow.AddSeconds(5), signingCredentials: credentials);
                var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
                return new { token, roleList, appUser.Avatar };//完成登入後,回傳給前端token與role list以及大頭照資訊
            }
            catch (Exception ex)
            {
                throw;
            }
        }



    }
}


密鑰的長度要盡可能設長不然會報錯
IDX10653: The encryption algorithm 'System. String' requires a key size of at least 'System. Int32' bits. 





Ref:
IDX10653: The encryption algorithm 'System. String' requires a key size of at least 'System. Int32' bits. 
https://www.cnblogs.com/jiujiaoxiaoshun/p/16627792.html

留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題