Authentication and authorization (two)
前言
這篇緊接著一來寫的,在第一篇中介紹了認證與授權,同時提出了這套機制其實就是模擬現實中的認證與授權。
同樣這篇介紹在這套機制下,使用者資訊管理機制?這裡就會問了,上一篇中認證和授權不是都ok了嗎,怎麼會有一個管理機制呢?當然並不一定要使用下面這套機制,但是給了我們很大的啟發。
在上一結中我們頒發證書是這樣的:
public IActionResult Authenticate() { var SchoolClaims = new List<Claim>() { new Claim(ClaimTypes.Name,"Jack"), new Claim(ClaimTypes.Email,"[email protected]") }; var LicensClaims = new List<Claim>() { new Claim(ClaimTypes.Name,"Jack.li"), new Claim(ClaimTypes.Email,"[email protected]"), new Claim("begin","2000.10.1") }; var SchoolIdentity = new ClaimsIdentity(SchoolClaims,"Student Identity"); var CarManagerIdentity = new ClaimsIdentity(LicensClaims, "Licens Identity"); var userPrincipal = new ClaimsPrincipal(new[] { SchoolIdentity, CarManagerIdentity }); HttpContext.SignInAsync(userPrincipal); return RedirectToAction("Index"); }
有沒有發現new Claim(ClaimTypes.Name,"Jack") 寫死了?我的資訊是要從資料庫裡面查啊。
這時候微軟的框架就跳出來了,說用我的這套機制,幫你搞定,到底是什麼機制呢?請看正文。小聲逼逼一句,微軟就喜歡搞全包工程。
正文均為個人理解,如有不對請指出。
正文
首先提及到一個結構,IdentityUser,這東西是真的博大精深,但是感覺有點臃腫,這很微軟。
IdentityUser 這裡可以簡單說明一下,就是儲存使用者資訊的地方。
既然說到使用者儲存,那麼就要提及到資料庫了。
建立了一個AppDbContext:
public class AppDbContext:IdentityDbContext { public AppDbContext(DbContextOptions<AppDbContext> options):base(options) { } }
以前我們一般是繼承DbContext,DbContext是Ef的上下文。
這裡IdentityDbContext,是Ef的擴充套件,看下我添加了什麼。
紅色框內是我新增的。
在這裡我為了演示使用記憶體資料庫memory,所以我多加了一個庫。
然後我在startup中配置使用memory資料庫。
services.AddDbContext<AppDbContext>(config =>{
config.UseInMemoryDatabase("Memery");
});
這樣就配置了,現在就解決了資料庫的問題。
同樣需要配置identity:
services.AddIdentity<IdentityUser, IdentityRole>(config=> {
config.Password.RequiredLength = 4;
config.Password.RequireDigit = false;
config.Password.RequireNonAlphanumeric = false;
config.Password.RequireLowercase = false;
config.Password.RequireUppercase = false;
}).AddEntityFrameworkStores<AppDbContext>().AddDefaultTokenProviders();
有幾個關鍵的地方,就是config.Password.RequiredLength = 4;等幾個password的配置,
因為identetyUser 有預設的機制就是密碼必須要大寫,然後不小於6位密碼等,我們在這裡全部去掉。
AddEntityFrameworkStores() 新增EF 儲存實現。
AddDefaultTokenProviders() 預設提供生成token。這種token 用來幹啥呢?當然是用來證明使用者的了。比如我們修改密碼的時候,我們發現連結上有一個token,異曲同工之妙哈。
services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "Identity.Cooke";
config.LoginPath = "/Home/Login";
});
加上驗證,當沒有登陸的時候去到登陸頁面。
好的配置我們基本完成了。
接下來就是去實現登陸與註冊。
public IActionResult Index()
{
return View();
}
public IActionResult Secret()
{
return View();
}
public IActionResult Login()
{
return View();
}
public IActionResult Register()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(string username, string password)
{
var user = await _userManager.FindByNameAsync(username);
if (user != null)
{
//sign in
var Signresult= await _signInManager.PasswordSignInAsync(user,password,false,false);
if (Signresult.Succeeded)
{
return RedirectToAction("Secret");
}
}
return RedirectToAction("Index");
}
[HttpPost]
public async Task<IActionResult> Register(string username,string password)
{
var user = new IdentityUser
{
UserName = username,
Email = ""
};
var result=await _userManager.CreateAsync(user,password);
if (result.Succeeded)
{
var Signresult = await _signInManager.PasswordSignInAsync(user, password, false, false);
if (Signresult.Succeeded)
{
return RedirectToAction("Index");
}
}
return RedirectToAction("Index");
}
看到兩個http post:
先看Register:
建立了IdentityUser,用來儲存使用者資訊。
_userManager 是用來管理user使用者的,比如說建立,刪除,修改,是identetyUser 內部機制。
建立過程如下:
public HomeController(UserManager<IdentityUser> userManager,SignInManager<IdentityUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
var result=await _userManager.CreateAsync(user,password); 如果建立使用者成功,那麼就進行登陸如下:
var Signresult = await _signInManager.PasswordSignInAsync(user, password, false, false);
注意PasswordSignInAsync登陸的話會產生token,用於驗證我們是否登陸。
當我註冊後,產生了token,如下:
看下登陸,其實我們在註冊部分就已經介紹了登陸了。
我重新把程式碼放下了:
var user = await _userManager.FindByNameAsync(username);
if (user != null)
{
//sign in
var Signresult= await _signInManager.PasswordSignInAsync(user,password,false,false);
if (Signresult.Succeeded)
{
return RedirectToAction("Secret");
}
}
return RedirectToAction("Index");
發現就多了一步,根據名字去查詢user,如果有這個user,然後去比較密碼。和平時寫code 差不多。
然後登陸後就可以進入了我們想進入的頁面。
如果我們想loginout:
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index");
}
把登陸和註冊的頁面貼下:
login:
<form action="/Home/Login" method="post">
<input type="text" name="username" value="" />
<input type="password" name="password" value="" />
<button type="submit">登陸</button>
</form>
註冊:
<form action="/Home/Register" method="post">
<input type="text" name="username" value="" />
<input type="password" name="password" value="" />
<button type="submit">註冊</button>
</form>
在上一篇中,就很疑問了,上一篇沒有登入啊。
真的沒有登入嗎?只是用證書去登入了,不然怎麼能過的了檢查呢。
HttpContext.SignInAsync("CookieAuth", userPrincipal);
總結
現在我們的流程更加的明顯了,先要驗證使用者資訊,比如說是否登入了,這個過程相當於什麼呢?我們用我們的名字和指紋(password),去獲取到了我們的身份證。有了這張身份證後我們才有其他的證書,然後才有根據證書去獲取一些許可權。
後續介紹基本的配置,與原理。