Popular blog tags

在 asp .net core web项目中,认证方式有好几种,如下:

 

step 1: 安装cookie认证中间件 安装包

 

 

step 2:配置项目的认证方式为cookie认证

  #region 配置cookie认证方式
            //see:https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x
            // If you don't want the cookie to be automatically authenticated and assigned to HttpContext.User, 
            // remove the CookieAuthenticationDefaults.AuthenticationScheme parameter passed to AddAuthentication.
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = "/Customer/LogIn";
                    options.LogoutPath = "/Customer/LogOut";
#if !DEBUG
                    options.Cookie.Domain = ".iaspnetcore.com";//设置Cookie的域为根域,这样所有子域都可以发现这个Cookie
#endif
                }
               );



            #endregion

 

step 3:启用认证

   app.UseAuthentication();
    app.UseAuthorization();

 

step 4:登陆

登陆采用HttpContext.SignInAsync(),我们要做的,只是构造出此函数需要的参数即可。

       我们最终要构造的参数是一个ClaimsPrincipal对象。构造过程简述如下:把用户名和用户角色(权限信息)保存到一个claims对象,用claims对象构造出claimsIdentity 对象,用claimsIdentity 对象构造出ClaimsPrincipal对象。

        调用HttpContext.SignInAsync方法登陆,登录成功后,这个方法会在HttpContext.Response的Header中响应头中添加Set-Cookie,cookie的内容就是ClaimsPrincipal对象加密后的字符串。

        同时把这个ClaimsPrincipal对象保存到HttpContext.User

 [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]

        public async Task<IActionResult> Login(LoginModel model)
        {
            

            this.TryValidateModel(model);
         

            if (ModelState.IsValid)
            {
                //获取用户
                var customer = await this._customerService.GetCustomerByUsernameAsync(model.Username.Trim());

                if (customer == null)
                {
                    ModelState.AddModelError("LogonUsernameNotExist", "用户名不存在");
                    return View(model);
                }

                var encryptPassword = model.Password;
                if (customer.PasswordFormat== PasswordFormat.aspMd5)
                {
                    encryptPassword = aspMD5.Encrypt(model.Password, 16);

                }
                

                if (!(customer.Password == encryptPassword))
                {
                    ModelState.AddModelError("LogonErrorPassword", "密码不正确");
                    return View(model);
                }



                //cookie 登陆 

                // claims 
                var claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.Name, customer.Username));

                //角色
                foreach (var role in customer.CustomerRoles)
                {
                    //添加角色时使用自带的ClaimTypes.Role就不需要在新建ClaimsIdentity时指定角色验证类型
                    claims.Add(new Claim(ClaimTypes.Role, role.SystemName));
                }

                var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

                var authProperties = new AuthenticationProperties
                {
                    
                };

                // 登录

                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);


                ////修改登录信息
                customer.LastLoginDateUtc = DateTime.UtcNow;
                customer.LastIpAddress = _webHelper.GetCurrentIpAddress();
                await this._customerService.UpdateCustomerAsync(customer);

                _workContext.CurrentCustomer = customer;

                return RedirectToAction("Index", "Home");



            }



            //If we got this far, something failed, redisplay form

            return View(model);
        }

 

NET Core中通过Microsoft.AspNetCore.Authentication.Cookies这个中间件识别HttpContext中认证相关的Cookie,以后浏览器访问时,HttpContext.Request都会带有这个Cookie,Cookie中间件会把Cookie取出来,解密并还原为ClaimsPrincipal对象,并把HttpContext.User设置为这个对象。后面MVC中间件在路由到相应Controller和Action的时候就可以根据Authorize特性中指定的认证和角色在HttpContext.User中进行检查,不满足检查则跳转至相应页面。因此需要注意的就是一定要把Cookie中间件放在MVC中间件之前。

 

logout

注销很简单,直接调用 _httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);注销,其原理是HttpContext.SignOutAsync()会在HttpContext.Response添加Set-Cookie,但cookie内容为空。

  public async Task<IActionResult> Logout()
        {
            //external authentication


            //注销  cookie
           //and sign out from the current authentication scheme
            await _httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

            
            return RedirectToAction("Index", "Home");

        }