前言
这篇紧接着一来写的, 在第一篇中介绍了认证与授权, 同时提出了这套机制其实就是模拟现实中的认证与授权.
同样这篇介绍在这套机制下, 用户信息管理机制? 这里就会问了, 上一篇中认证和授权不是都 ok 了吗, 怎么会有一个管理机制呢? 当然并不一定要使用下面这套机制, 但是给了我们很大的启发.
在上一结中我们颁发证书是这样的:
- public IActionResult Authenticate()
- {
- var SchoolClaims = new List<Claim>()
- {
- new Claim(ClaimTypes.Name,"Jack"),
- new Claim(ClaimTypes.Email,"Jack@fmail.com")
- };
- var LicensClaims = new List<Claim>()
- {
- new Claim(ClaimTypes.Name,"Jack.li"),
- new Claim(ClaimTypes.Email,"Jack@fmail.com"),
- 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), 去获取到了我们的身份证. 有了这张身份证后我们才有其他的证书, 然后才有根据证书去获取一些权限.
后续介绍基本的配置, 与原理.
来源: https://www.cnblogs.com/aoximin/p/12271471.html