zoukankan      html  css  js  c++  java
  • ASP.NET Core Authentication系列(二)实现认证、登录和注销

    前言

    上一篇文章介绍ASP.NET Core Authentication的三个重要概念,分别是Claim, ClaimsIdentity, ClaimsPrincipal,以及claims-base authentication是怎么工作的。

    这篇文章来介绍一下如何基于claims-base authentication来实现认证、登录和注销功能的。源代码从这里下载。

    认证票据

    认证是一个确定发送请求的访问者身份的过程,与认证相关的还有另外两个基本操作:登录和注销。

    ASP.NET Core应用的认证实现在一个名为AuthenticationMiddleware的中间件中,该中间件在处理分发给它的请求时会按照指定的 认证方案(Authentication Scheme) 从请求中提取能够验证用户真实身份的数据,我们一般将该数据称为 安全令牌(Security Token) 。ASP.NET Core应用下的安全令牌被称为 认证票据(Authentication Ticket) ,所以ASP.NET Core应用采用基于票据的认证方式。

    AuthenticationMiddleware中间件的整个认证过程涉及下图的三种操作:认证票据的颁发、检验和撤销。

    image

    ASP.NET Core应用的认证系统旨在构建一个标准的模型来完成针对请求的认证以及与之相关的登录和注销操作。接下来我们就通过一个简单的实例来演示如何在一个ASP.NET Core应用中实现认证、登录和注销的功能。

    基于Cookie的认证

    大多数Web应用采用的是Cookie来保存认证票据,因此我们采用基于Cookie的认证方案。

    配置

    Startup.ConfigureServices方法里,添加AuthenticationMiddleware中间件:

    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie();
    

    然后在Startup.Configure方法里,调用UseAuthenticationUseAuthorization来设置HttpContext.User属性以及允许请求经过AuthenticationMiddleware,并且要在UseEndpoints之前调用:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...
        
        app.UseAuthentication();
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
            
        // ...
    }
        
    

    登录

    接下来实现登录方法,常见是使用“用户名+密码”,这里使用一个静态字典来模拟用户表。

    public class AccountController : Controller
    {
        // ....
    
        private static Dictionary<string, string> _accounts;
    
        static AccountController()
        {
            _accounts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            _accounts.Add("Foo", "password");
            _accounts.Add("Bar", "password");
            _accounts.Add("Baz", "password");
        }
    
        [HttpGet]
        public IActionResult Login()
        {
            LoginModel model = new LoginModel();
    
            return View(model);
        }
    
        [HttpPost]
        public async Task<IActionResult> Login(LoginModel model)
        {
            if (_accounts.TryGetValue(model.UserName, out var pwd) && pwd == model.Password)
            {
                var claimsIdentity = new ClaimsIdentity(
                    new Claim[] { new Claim(ClaimTypes.Name, model.UserName) }, "Basic");
                var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);                
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
    
                return Redirect("/");
            }
            else
            {
                model.ErrorMessage = "Invalid user name or password!";
    
                return await Task.Run(() => View(model));
            }
        }
    
        // ....
    }
    

    这段代码的关键在于下面三行代码:

    1. 创建ClaimType为Name,值为用户名的Claim。
    2. 创建ClaimsIdentity,注意AuthorizeType="Basic"。
    3. 创建ClaimsPrincipal。
    4. 调用HttpContext.SignInAsync登录,其中认证方案为CookieAuthenticationDefaults.AuthenticationScheme,与配置时一致。
    var claimsIdentity = new ClaimsIdentity(
        new Claim[] { new Claim(ClaimTypes.Name, model.UserName) }, "Basic");
    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); 
    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
    

    认证

    需要授权访问的功能要验证登录状态,如果没有登录则不允许访问,使用方法很简单,只需要在Action上加上特性[Authorize]

    [Authorize]
    public IActionResult Index()
    {
        return View();
    }
    

    未登录会跳转到/Account/Login(默认设置,可修改),避免未授权访问。

    注销

    用户注释,即将具有认证票据的Cookie设置为过期,直接调用HttpContext.SignOutAsync,注意认证方案要与配置和登录的一致:CookieAuthenticationDefaults.AuthenticationScheme

    public class AccountController : Controller
    {
        // ....
    
        public async Task<IActionResult> Logout()
        {
            _logger.LogInformation("User {Name} logged out at {Time}.",
                    User.Identity.Name, DateTime.UtcNow);
    
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    
            return Redirect("/");
        }
        
        // ....
    }
    

    参考资料

  • 相关阅读:
    学习总结(二十六)
    学习总结(二十五)
    在知乎学习怎么参加工作
    连分数系列
    Kalman Filter
    五子棋的学习
    Dijkstra
    三等分角、化圆为方、倍立方体
    女朋友走丢数学模型
    传染病模型
  • 原文地址:https://www.cnblogs.com/liang24/p/13912695.html
Copyright © 2011-2022 走看看