ASP.NET Core 打造一個簡單的圖書館管理系統(三)基本登陸頁面以及受權邏輯的創建

前言:git

本系列文章主要爲我以前所學知識的一次微小的實踐,以我學校圖書館管理系統爲雛形所做。github

本系列文章主要參考資料:數據庫

微軟文檔:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windowswindows

《Pro ASP.NET MVC 5》、《鋒利的 jQuery》數組

 

當此系列文章寫完後會在一週內推出修正版。安全

 

此係列皆使用 VS2017+C# 做爲開發環境。若是有什麼問題或者意見歡迎在留言區進行留言。 app

項目 github 地址:https://github.com/NanaseRuri/LibraryDemo框架

 

 

  本章內容:Identity 框架的配置、對帳戶進行受權的配置、數據庫的初始化方法、自定義 TagHelperasync

 

 

 一到四爲對 Student 即 Identity框架的使用,第五節爲對 Admin 用戶的配置ide

 

 

 

1、自定義帳號和密碼的限制

  在 Startup.cs 的 ConfigureServices 方法中能夠對 Identity 的帳號和密碼進行限制:

 1             services.AddIdentity<Student, IdentityRole>(opts =>
 2                 {
 3                     opts.User.RequireUniqueEmail = true; 4 opts.User.AllowedUserNameCharacters = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789"; 5 opts.Password.RequiredLength = 6; 6 opts.Password.RequireNonAlphanumeric = false; 7 opts.Password.RequireLowercase = false; 8 opts.Password.RequireUppercase = false; 9 opts.Password.RequireDigit = false; 10 }).AddEntityFrameworkStores<StudentIdentityDbContext>() 11 .AddDefaultTokenProviders();

  RequireUniqueEmail 限制每一個郵箱只能用於一個帳號。

  此處 AllowedUserNameCharacters 方法限制用戶名可以使用的字符,須要單獨輸入每一個字符。

  剩下的設置分別爲限制密碼必須有符號 / 包含小寫字母 / 包含大寫字母 / 包含數字。

 

 

 

 

2、對數據庫進行初始化

  在此建立一個 DatabaseInitiator 用以對數據庫進行初始化:

 1         public static async Task Initial(IServiceProvider serviceProvider)
 2  { 3 UserManager<Student> userManager = serviceProvider.GetRequiredService<UserManager<Student>>(); 4 if (userManager.Users.Any()) 5  { 6 return; 7  } 8 IEnumerable<Student> initialStudents = new[] 9  { 10 new Student() 11  { 12 UserName = "U201600001", 13 Name = "Nanase", 14 Email = "Nanase@cnblog.com", 15 PhoneNumber = "12345678910", 16 Degree = Degrees.CollegeStudent, 17 MaxBooksNumber = 10, 18  }, 19 new Student() 20  { 21 UserName = "U201600002", 22 Name = "Ruri", 23 Email = "NanaseRuri@cnblog.com", 24 PhoneNumber = "12345678911", 25 Degree = Degrees.DoctorateDegree, 26 MaxBooksNumber = 15 27  }, 28  }; 29 30 foreach (var student in initialStudents) 31  { 32 await userManager.CreateAsync(student, student.UserName.Substring(student.UserName.Length - 6,6)); 33  } 34 }

 

  爲確保可以進行初始化,在 Configure 方法中調用該靜態方法:  

1             app.UseMvc(routes =>
2             {
3  routes.MapRoute( 4 name: "default", 5 template: "{controller=Home}/{action=Index}/{id?}"); 6  }); 7 DatabaseInitiator.Initial(app.ApplicationServices).Wait();

  Initial 方法中 serviceProvider 參數將在傳入 ConfigureServices 方法調用後的 ServiceProvider,此時在 Initial 方法中初始化的數據也會使用 ConfigureServices 中對帳號和密碼的限制。

  此處咱們使用帳號的後六位做爲密碼。啓動網頁後查看數據庫的數據:

 

 

 

 

3、創建驗證所用的控制器以及視圖

  首先建立一個視圖模型用於存儲帳號的信息,爲了方便實現多種登陸方式,此處建立一個 LoginType 枚舉:

  [UIHint] 特性構造函數傳入一個字符串用來告知在 <input/> 中時用什麼模板來展現數據。

    public enum LoginType
    {
        UserName,
        Email,
        Phone
    }

    public class LoginModel { [Required(ErrorMessage = "請輸入您的學號 / 郵箱 / 手機號碼")] [Display(Name = "學號 / 郵箱 / 手機號碼")] public string Account { get; set; } [Required(ErrorMessage = "請輸入您的密碼")] [UIHint("password")] [Display(Name = "密碼")] public string Password { get; set; } [Required] public LoginType LoginType { get; set; } }

 

   使用支架特性建立一個 StudentAccountController

 

 1     public class StudentAccountController : Controller
 2  { 3 public IActionResult Login(string returnUrl) 4  { 5 LoginModel loginInfo=new LoginModel(); 6 ViewBag.returnUrl = returnUrl; 7 return View(loginInfo); 8  } 9   }

 

  先建立普通的 Login 視圖:

 1 @model LoginModel
 2 
 3 @{ 4 ViewData["Title"] = "Login"; 5 } 6 7 <h2>Login</h2> 8 <br/> 9 <div class="text-danger" asp-validation-summary="All"></div> 10 <br/> 11 <form asp-action="Login" method="post"> 12 <input type="hidden" name="returnUrl" value="@ViewBag.returnUrl"/> 13 <div class="form-group"> 14 <label asp-for="Account"></label> 15 <input asp-for="Account" class="form-control" placeholder="請輸入你的學號 / 郵箱 / 手機號"/> 16 </div> 17 <div class="form-group"> 18 <label asp-for="Password"></label> 19 <input asp-for="Password" class="form-control" placeholder="請輸入你的密碼"/> 20 </div> 21 <div class="form-group"> 22 <label>登陸方式</label> 23 <select asp-for="LoginType"> 24 <option disabled value="">登陸方式</option> 25 <LoginType login-type="@Enum.GetNames(typeof(LoginType))"></LoginType> 26 </select> 27 </div> 28 <input type="submit" class="btn btn-primary"/> 29 </form>

  在此爲添加多種登陸方式,並使視圖更加清晰,建立了一個 LoginTypeTagHelper ,TagHelper 可制定自定義 HTML 標記並在最終生成視圖時轉換成標準的 HTML 標記。

 1     [HtmlTargetElement("LoginType")]
 2     public class LoginTypeTagHelper:TagHelper 3  { 4 public string[] LoginType { get; set; } 5 6 public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) 7  { 8 foreach (var loginType in LoginType) 9  { 10 switch (loginType) 11  { 12 case "UserName": output.Content.AppendHtml($"<option selected=\"selected/\" value=\"{loginType}\">學號</option>"); 13 break; 14 case "Email": output.Content.AppendHtml(GetOption(loginType, "郵箱")); 15 break; 16 case "Phone": output.Content.AppendHtml(GetOption(loginType, "手機號碼")); 17 break; 18 default: break; 19  } 20  } 21 return Task.CompletedTask; 22  } 23 24 private static string GetOption(string loginType,string innerText) 25  { 26 return $"<option value=\"{loginType}\">{innerText}</option>"; 27  } 28 }

 

 

  而後建立一個用於對信息進行驗證的動做方法。

  爲了獲取數據庫的數據以及對數據進行驗證受權,須要經過 DI(依賴注入) 獲取對應的 UserManager 和 SignInManager 對象,在此針對 StudentAccountController 的構造函數進行更新。

  StudentAccountController 總體:

 1 public class StudentAccountController : Controller
 2  { 3 private UserManager<Student> _userManager; 4 private SignInManager<Student> _signInManager; 5 6 public StudentAccountController(UserManager<Student> studentManager, SignInManager<Student> signInManager) 7  { 8 _userManager = studentManager; 9 _signInManager = signInManager; 10  } 11 12 public IActionResult Login(string returnUrl) 13  { 14 LoginModel loginInfo = new LoginModel(); 15 ViewBag.returnUrl = returnUrl; 16 return View(loginInfo); 17  } 18 19  [HttpPost] 20  [ValidateAntiForgeryToken] 21 public async Task<IActionResult> Login(LoginModel loginInfo, string returnUrl) 22  { 23 if (ModelState.IsValid) 24  { 25 Student student =await GetStudentByLoginModel(loginInfo); 26 27 if (student == null) 28  { 29 return View(loginInfo); 30  } 31 SignInResult signInResult = await _signInManager.PasswordSignInAsync(student, loginInfo.Password, false, false); 32 33 if (signInResult.Succeeded) 34  { 35 return Redirect(returnUrl ?? "/StudentAccount/"+nameof(AccountInfo)); 36  } 37 38 ModelState.AddModelError("", "帳號或密碼錯誤"); 39 40  } 41 42 return View(loginInfo); 43  } 44 45  [Authorize] 46 public IActionResult AccountInfo() 47  { 48 return View(CurrentAccountData()); 49  } 50 51 Dictionary<string, object> CurrentAccountData() 52  { 53 var userName = HttpContext.User.Identity.Name; 54 var user = _userManager.FindByNameAsync(userName).Result; 55 56 return new Dictionary<string, object>() 57  { 58 ["學號"]=userName, 59 ["姓名"]=user.Name, 60 ["郵箱"]=user.Email, 61 ["手機號"]=user.PhoneNumber, 62  }; 63 }

  _userManager 以及  _signInManager 將經過 DI 得到實例;[ValidateAntiForgeryToken] 特性用於防止 XSRF 攻擊;returnUrl 參數用於接收或返回以前正在訪問的頁面,在此處若 returnUrl 爲空則返回 AccountInfo 頁面;[Authorize] 特性用於確保只有已受權的用戶才能訪問對應動做方法;CurrentAccountData 方法用於獲取當前用戶的信息以在 AccountInfo 視圖中呈現。

 

  因爲未進行受權,在此直接訪問 AccountInfo 方法默認會返回 /Account/Login 頁面請求驗證,可經過在 ConfigureServices 方法進行配置以覆蓋這一行爲,讓頁面默認返回 /StudentAccount/Login :

1             services.ConfigureApplicationCookie(opts =>
2             {
3                 opts.LoginPath = "/StudentAccount/Login"; 4 });

 

  爲了使 [Authorize] 特性可以正常工做,須要在 Configure 方法中使用 Authentication 中間件,若是沒有調用app.UseAuthentication(),則訪問帶有 [Authorize] 的方法會再度要求進行驗證。中間件的順序很重要:

1             app.UseAuthentication();
2  app.UseHttpsRedirection(); 3  app.UseStaticFiles(); 4 app.UseCookiePolicy();

 

  同時在 ConfigureServices 中對 Cookie 策略進行配置:

1             services.Configure<CookiePolicyOptions>(options =>
2             {
3                 options.CheckConsentNeeded = context => true; 4 options.MinimumSameSitePolicy = SameSiteMode.None; 5 });

 

  直接訪問 AccountInfo 頁面:

 

  輸入帳號密碼進行驗證:

 

  驗證以後返回 /StudentAccount/AccountInfo 頁面:

 

 

 

4、建立登出網頁

  簡單地調用 SignOutAsync 用以清除當前 Cookie 中的受權信息。

1         [Authorize]
2         public async Task<IActionResult> Logout() 3  { 4 await _signInManager.SignOutAsync(); 5 return View("Login"); 6 }

 

  同時在 AccountInfo 添加登出按鈕:

 1     @model Dictionary<string, object>
 2     @{
 3         ViewData["Title"] = "AccountInfo"; 4  } 5 <h2>帳戶信息</h2> 6 <ul> 7 @foreach (var info in Model) 8  { 9 <li>@info.Key: @Model[info.Key]</li> 10  } 11 </ul> 12 <br /> 13 <a class="btn btn-danger" asp-action="Logout">登出</a>

 

 

  登出後返回 Login 頁面,同時 AccountInfo 頁面須要從新進行驗證。

 

  附加使用郵箱以及手機號驗證的測試:

 

 

  最後對 Login 動做方法進行修改以免沒必要要的驗證:

 1         public IActionResult Login(string returnUrl)
 2  { 3 if (HttpContext.User.Identity.IsAuthenticated) 4  { 5 return RedirectToAction("AccountInfo"); 6  } 7 8 LoginModel loginInfo = new LoginModel(); 9 ViewBag.returnUrl = returnUrl; 10 return View(loginInfo); 11 }

 

  已受權狀況下再度訪問 Login 方法返回 AccountInfo :

 

  登出後再次訪問 AccountInfo 方法: 

 

 

  登出後須要從新驗證:

 

 

 

五?、Admin,不可與 Identity 同時使用的基於 Cookie 的受權?

  帶有自定義驗證邏輯項目地址:https://files-cdn.cnblogs.com/files/gokoururi/LibraryDemo-Failed.zip

 

  原本打算使用 Cookie 進行對 Admin 的受權,但因爲 Identity 使用的也是基於 Cookie 的受權並作了大量的工做,同時使用二者在一些奇奇怪怪的地方會出現 bug,若是有什麼解決方案感謝不盡,所以這節只作使用 Cookie 受權的演示。

 

  爲使用 Cookie 受權,須要在 ConfigureServices 和 Configure 方法中進行配置:

  ConfigureServices 中調用 services.AddAuthentication 啓用驗證,使用 CookieAuthenticationDefaults.AuthenticationScheme 做爲默認該驗證的 scheme,使用默認 Cookie 沿驗證。

1             services.AddAuthentication(options =>
2                 {
3                     options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 4  }) 5 .AddCookie();

 

  爲保證安全,密碼不能使用明文保存在數據庫中,所以在此使用 MD5 加密對密碼進行加密。在此建立一個類用以更方便地調用:

  建立 Encrptor 類,設置私有默認構造函數防止該類被實例化,添加靜態方法 MD5Encrypt32 用以返回加密後的字符串:

 1     public class Encryptor
 2  { 3 private Encryptor() 4  { 5  } 6 7 public static string MD5Encrypt(string password) 8  { 9 MD5 md5 = MD5.Create(); 10 byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(password)); 11 StringBuilder hashPassword = new StringBuilder(); 12 foreach (var b in hashBytes) 13  { 14  hashPassword.Append(b); 15  } 16 17 return hashPassword.ToString(); 18  } 19 }

 

  在此處要注意使用 context.SaveChanges 來保存對數據庫作出的增刪改的操做,不然數據庫將不會作出更改。對 AdminDbContext 進行初始化:

 1     public class AdminInitiator
 2  { 3 public static async Task InitialAdmins(IServiceProvider serviceProvider) 4  { 5 AdminDbContext adminDbContext = serviceProvider.GetRequiredService<AdminDbContext>(); 6 if (adminDbContext.Admins.Any()) 7  { 8 return; 9  } 10 11 IEnumerable<Admin> admins = new[] 12  { 13 new Admin() 14  { 15 UserName = "admin", 16 Email = "admin@cnblog.com", 17 PhoneNumber = "10000000000", 18 Password = "123456" 19  }, 20 new Admin() 21  { 22 UserName = "admin1", 23 Email = "admin1@cnblog.com", 24 PhoneNumber = "10000000001", 25 Password = "456789" 26  }, 27  }; 28 29 foreach (var admin in admins) 30  { 31  EncryptAdmin(admin); 32 await adminDbContext.AddAsync(admin); 33 await adminDbContext.SaveChangesAsync(); 34  } 35  } 36 37 private static Admin EncryptAdmin(Admin admin) 38  { 39 admin.Password = Encryptor.MD5Encrypt(admin.Password); 40 return admin; 41  } 42 }

 

  此處爲 Authorize 特性指定受權的 Scheme,則能夠經過不一樣的 Scheme 指定不一樣的受權。指定 [AllowAnoymous] 特性時,該方法能夠在未受權的狀況下被訪問。

  1     [Authorize(AuthenticationSchemes=CookieAuthenticationDefaults.AuthenticationScheme)]
  2     public class AdminAccountController : Controller 3  { 4 private AdminDbContext _context; 5 6 public AdminAccountController(AdminDbContext context) 7  { 8 _context = context; 9  } 10 11  [AllowAnonymous] 12 public IActionResult Login(string returnUrl) 13  { 14 if (HttpContext.User.IsInRole("admin")) 15  { 16 return RedirectToAction("Index"); 17  } 18 LoginModel model = new LoginModel(); 19 return View(model); 20  } 21 22 public IActionResult Index() 23  { 24 return View(CurrentAccountData()); 25  } 26 27  [HttpPost] 28  [ValidateAntiForgeryToken] 29  [AllowAnonymous] 30 public async Task<IActionResult> Login(LoginModel loginInfo, string returnUrl) 31  { 32 if (ModelState.IsValid) 33  { 34 Admin admin = new Admin(); 35 switch (loginInfo.LoginType) 36  { 37 case LoginType.UserName: 38 admin = await _context.Admins.FirstOrDefaultAsync(a => a.UserName == loginInfo.Account); 39 break; 40 case LoginType.Email: 41 admin = await _context.Admins.FirstOrDefaultAsync(a => a.Email == loginInfo.Account); 42 break; 43 case LoginType.Phone: 44 admin = await _context.Admins.FirstOrDefaultAsync(a => a.PhoneNumber == loginInfo.Account); 45 break; 46 default: 47 admin = null; 48 break; 49  } 50 51 if (admin != null) 52  { 53 string encryptedPassword = Encryptor.MD5Encrypt32(loginInfo.Password); 54 if (admin.Password == encryptedPassword) 55  { 56 ClaimsIdentity identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme); 57 identity.AddClaims(new[] 58  { 59 new Claim(ClaimTypes.Name, admin.UserName), 60 new Claim(ClaimTypes.Email,admin.Email), 61 new Claim(ClaimTypes.MobilePhone,admin.PhoneNumber), 62 new Claim(ClaimTypes.Role,"admin"), 63  }); 64 var principal = new ClaimsPrincipal(identity); 65 await HttpContext.SignInAsync(principal,new AuthenticationProperties() 66  { 67 ExpiresUtc = DateTime.UtcNow.AddSeconds(8) 68  }); 69 70 if (returnUrl != null) 71  { 72 return Redirect(returnUrl); 73  } 74 75 return RedirectToAction("Index"); 76  } 77  } 78 ModelState.AddModelError("", "帳號或密碼錯誤"); 79 return View(loginInfo); 80  } 81 82 return View(loginInfo); 83  } 84 85  [Authorize] 86 public async Task<IActionResult> Logout() 87  { 88 await HttpContext.SignOutAsync(); 89 return View("Login"); 90  } 91 92 Dictionary<string, object> CurrentAccountData() 93  { 94 var userName = HttpContext.User.Identity.Name; 95 var user = _context.Admins.FirstOrDefault(a => a.UserName == userName); 96 97 return new Dictionary<string, object>() 98  { 99 ["用戶名"] = user.UserName, 100 ["郵箱"] = user.Email, 101 ["手機號"] = user.PhoneNumber, 102  }; 103  } 104 }

 

  因爲 Login 視圖和 StudentAccountController 的 Login 視圖大體一致,所以能夠將重複的部分提取出來做爲一個分部視圖,在 Views/Shared 文件夾中建立分部視圖:

 

 1     @model LoginModel
 2 
 3     <input type="hidden" name="returnUrl" value="@ViewBag.returnUrl"/>
 4     <div class="form-group">   
 5         <label asp-for="Account"></label>
 6         <input asp-for="Account" class="form-control" placeholder="請輸入你的帳號(學號) / 郵箱 / 手機號"/>
 7     </div>
 8     <div class="form-group">   
 9         <label asp-for="Password"></label>
10         <input asp-for="Password" class="form-control" placeholder="請輸入你的密碼"/>
11     </div>
12     <div class="form-group">
13         <label>登陸方式</label>
14         <select asp-for="LoginType">
15             <option disabled value="">登陸方式</option>
16             <LoginType login-type="@Enum.GetNames(typeof(LoginType))"></LoginType>
17         </select>
18     </div>
19     <input type="submit" class="btn btn-primary"/>
20     <input type="reset" class="btn btn-primary"/>

 

  對 StudentAccountController 的 Login 視圖作出修改:

 1     @model LoginModel
 2 
 3  @{ 4 ViewData["Title"] = "Login"; 5  } 6 7 <h2>Login</h2> 8 <br/> 9 <div class="text-danger" asp-validation-summary="All"></div> 10 <br/> 11 <form asp-action="Login" method="post"> 12 @await Html.PartialAsync("_LoginPartialView",Model) 13 </form>

 

  設置 AdminAccount 的 Login 視圖:

 1     @model LoginModel
 2  @{ 3 ViewData["Title"] = "AdminIndex"; 4  } 5 6 <h2>Login</h2> 7 <br /> 8 <div class="text-danger" asp-validation-summary="All"></div> 9 <br /> 10 <form asp-action="Login" method="post"> 11 @await Html.PartialAsync("_LoginPartialView", Model) 12 </form>

 

  AdminAccount 的 Index 視圖:

 1     @model Dictionary<string,object>
 2     @{
 3         ViewData["Title"] = "AccountInfo"; 4  } 5 6 <h2>AccountInfo</h2> 7 8 <ul> 9 @foreach (var info in Model) 10  { 11 <li>@info.Key: @Model[info.Key]</li> 12  } 13 14 </ul>

 

 

 

5、基於 Role 的 Identity 受權

  在此把以前全部與 Admin 有關的內容所有註釋掉或刪除,初始化身份爲 admin 的用戶。

  修改 StudentInitial 類,添加名爲 admin 的學生數組並使用 AddToRoleAsync 爲用戶添加身份。在添加 Role 以前須要在 RoleManager 對象中使用 Create 方法爲 Role 數據庫添加特定的 Role 字段:

 1     public class StudentInitiator
 2  { 3 public static async Task InitialStudents(IServiceProvider serviceProvider) 4  { 5 UserManager<Student> userManager = serviceProvider.GetRequiredService<UserManager<Student>>(); 6 RoleManager<IdentityRole> roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>(); 7 if (userManager.Users.Any()) 8  { 9 return; 10  } 11 12 if (await roleManager.FindByNameAsync("Admin")==null) 13  { 14 await roleManager.CreateAsync(new IdentityRole("Admin")); 15  } 16 17 if (await roleManager.FindByNameAsync("Student")==null) 18  { 19 await roleManager.CreateAsync(new IdentityRole("Student")); 20  } 21 22 IEnumerable<Student> initialStudents = new[] 23  { 24 new Student() 25  { 26 UserName = "U201600001", 27 Name = "Nanase", 28 Email = "Nanase@cnblog.com", 29 PhoneNumber = "12345678910", 30 Degree = Degrees.CollegeStudent, 31 MaxBooksNumber = 10, 32  }, 33 new Student() 34  { 35 UserName = "U201600002", 36 Name = "Ruri", 37 Email = "NanaseRuri@cnblog.com", 38 PhoneNumber = "12345678911", 39 Degree = Degrees.DoctorateDegree, 40 MaxBooksNumber = 15 41  } 42  }; 43 44 IEnumerable<Student> initialAdmins = new[] 45  { 46 new Student() 47  { 48 UserName = "A000000000", 49 Name="Admin0000", 50 Email = "Admin@cnblog.com", 51 PhoneNumber = "12345678912", 52 Degree = Degrees.CollegeStudent, 53 MaxBooksNumber = 20 54  } 55  }; 56 foreach (var student in initialStudents) 57  { 58 await userManager.CreateAsync(student, student.UserName.Substring(student.UserName.Length - 6, 6)); 59  } 60 foreach (var admin in initialAdmins) 61  { 62 await userManager.CreateAsync(admin, "zxcZXC!123"); 63 await userManager.AddToRoleAsync(admin, "Admin"); 64  } 65  } 66 }

 

  而後新建一個 Admin 控制器,設置 [Authorize] 特性並指定 Role 屬性,使帶有特定 Role 的身份才能夠訪問該控制器。

 1     [Authorize(Roles = "Admin")]
 2     public class AdminAccountController : Controller 3  { 4 private UserManager<Student> _userManager; 5 private SignInManager<Student> _signInManager; 6 7 public AdminAccountController(UserManager<Student> studentManager, SignInManager<Student> signInManager) 8  { 9 _userManager = studentManager; 10 _signInManager = signInManager; 11  } 12 13 public IActionResult Index() 14  { 15 return View(CurrentAccountData()); 16  } 17 18 19 20 Dictionary<string, object> CurrentAccountData() 21  { 22 var userName = HttpContext.User.Identity.Name; 23 var user = _userManager.FindByNameAsync(userName).Result; 24 25 return new Dictionary<string, object>() 26  { 27 ["學號"] = userName, 28 ["姓名"] = user.Name, 29 ["郵箱"] = user.Email, 30 ["手機號"] = user.PhoneNumber, 31  }; 32  } 33 }

 

  使用 Role 不是 Admin 的帳戶登陸:

 

 

   使用 Role 爲 Admin 的帳戶登陸:

 

   對 ConfigureServices 做進一步配置,添加 Cookie 的過時時間和不知足 Authorize 條件時返回的 Url:

            services.ConfigureApplicationCookie(opts =>
            {
 opts.Cookie.HttpOnly = true; opts.LoginPath = "/StudentAccount/Login";  opts.AccessDeniedPath = "/StudentAccount/Login"; opts.ExpireTimeSpan=TimeSpan.FromMinutes(5); });

   則當 Role 不爲 Admin 時將返回 /StudentAccount/Login 而非默認的 /Account/AccessDeny。

相關文章
相關標籤/搜索