µ±Ç°Î»Öà ²©ÎÄÊ×Ò³ > īīīīСÓÔÚ ASP.NET Core Ó¦ÓÃÖÐʹÓà Cookie ½øÐÐÉí·ÝÈÏÖ¤

    īīīīСÓÔÚ ASP.NET Core Ó¦ÓÃÖÐʹÓà Cookie ½øÐÐÉí·ÝÈÏÖ¤

    ×÷ÕߣºÄ«Ä«Ä«Ä«Ð¡Óî ʱ¼ä£º2021-02-01 10:22

    Overview

    Éí·ÝÈÏÖ¤ÊÇÍøÕ¾×î»ù±¾µÄ¹¦ÄÜ£¬×î½üÒòΪҵÎñ²¿ÃŵÄÒ»¸öÐèÇó£¬ÐèÒª¶ÔÒ»¸öÒѾ­´æÔںܾõÄС¹¤¾ßÍøÕ¾½øÐиÄÔ죬ÒòΪÔÚÖ𲽵Ľ«Ò»Ð©ÀëÉ¢µÄϵͳǨÒÆÖÁ .NET Core£¬ËùÒÔ³ÃÕâ¸ö»ú»á½«Õâ¸öÀ쵀 .NET Framework 4.0 µÄÏîÄ¿½øÐÐÉý¼¶

    ÀϵÄÏîÄ¿ÊÇÒ»¸ö MVC µÄÏîÄ¿²¢ÇÒÓÐÍâÍø·ÃÎʵÄÐèÇ󣬴ó²¿ÃŵÄ΢·þÎñƽ̨ÒòΪºÍÄÚ²¿µÄÒµÎñÖ´ÐбȽÏÃÜÇУ¬½éÓÚ×Ê°²ÒªÇóÓëÍâÍø½øÐÐÁ˸ôÀ룬Òò´Ë±¾´ÎÉý¼¶¾Í²»»áǨÒƵ½¸Ãƽ̨ÉϽøÐÐÇ°ºó¶Ë·ÖÀë¸ÄÔì

    ʹÓÃƵ´Î²»¸ß£¬²»´æÔڸ߲¢·¢£¬ÊµÏÖÖÜÆڶ̣¬ËùÒÔ¾ÍûÓбØҪΪÁËÓÃijЩ×é¼þ¶øÓã¬Òò´ËÕâÀﻹÊÇÑ¡ÔñÑØÓà MVC ¿ò¼Ü£¬¶ÔÓÚÍøÕ¾µÄÉí·ÝÈÏÖ¤Ôò²ÉÓõ¥ÌåÓ¦ÓÃ×î³£¼ûµÄ Cookie ÈÏÖ¤À´ÊµÏÖ£¬±¾ÆªÎÄÕÂÔòÊÇÈçºÎʵÏÖµÄÒ»¸ö»ù´¡µÄ½Ì³Ì£¬½ö¹©²Î¿¼

    Step by Step

    ÔÚÉæ¼°µ½ÏµÍ³È¨ÏÞ¹ÜÀíµÄÏà¹ØÄÚÈÝʱ£¬±Ø¶¨»áÌáµ½Á½¸ö³¤µÄºÜÏñµÄµ¥´Ê£¬authentication£¨ÈÏÖ¤£© ºÍ authorization£¨ÊÚȨ£©

    • authentication£ºÓÃһЩÊý¾ÝÀ´Ö¤Ã÷Äã¾ÍÊÇÄ㣬µÇ¼ϵͳ¡¢Ö¸ÎÆ¡¢Ã沿½âËø¾ÍÊÇÒ»ÖÖÈÏÖ¤µÄ¹ý³Ì
    • authorization£ºÊÚÓèһЩÓû§È¥·ÃÎÊһЩÌØÊâ×ÊÔ´»ò¹¦ÄܵĹý³Ì£¬ÏµÍ³°üº¬¹ÜÀíÔ±ºÍÆÕͨÓû§Á½ÖÖ½ÇÉ«£¬Ö»ÓйÜÀíÔ±²Å¿ÉÒÔÖ´ÐÐijЩ²Ù×÷£¬¸³Óè¹ÜÀíÔ±½ÇɫijЩ²Ù×÷µÄ¹ý³Ì¾ÍÊÇÊÚȨ

    Ö»ÓÐÈÏÖ¤ºÍÊÚȨһÆðÅäºÏ£¬²Å¿ÉÒÔÍê³É¶ÔÓÚÕû¸öϵͳµÄȨÏ޹ܿØ

    2.1¡¢Ç°ÆÚ×¼±¸

    ¼Ù¶¨ÏÖÔÚÒѾ­´æÔÚÁËÒ»¸ö ASP.NET Core MVC Ó¦Óã¬ÕâÀïÒÔ VS ´´½¨µÄĬÈÏÏîĿΪÀý£¬¶ÔÓÚÒ»¸ö MVC or Web API Ó¦Óã¬ÒªÇóÓû§±ØÐëµÇ¼֮ºó²ÅÄܽøÐзÃÎÊ£¬×î¼òµ¥µÄ·½Ê½£¬ÔÚÐèÒªÈÏÖ¤µÄ Controller »ò Action ÉÏÌí¼Ó Authorize ÌØÐÔ£¬È»ºóÔÚ Startup.Configure ·½·¨ÖÐͨ¹ý UseAuthorization Ìí¼ÓÖмä¼þ¼´¿É

    [Authorize]
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
    
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
    
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    "default",
                    "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
    

    µ±È»£¬µ±ÏµÍ³Ö»°üº¬Ò»¸öÁ½¸ö Controller ʱ»¹ºÃ£¬µ±ÏµÍ³±È½Ï¸´ÔÓµÄʱºò£¬ÔÙÒ»¸ö¸öµÄÌí¼Ó Authorize ÌØÐԾͱȽÏÂé·³ÁË£¬Òò´ËÕâÀïÎÒÃÇ¿ÉÒÔͨ¹ýÔÚ Startup.ConfigureServices ÖÐÌí¼ÓÈ«¾ÖµÄ AuthorizeFilter ¹ýÂËÆ÷£¬ÊµÏÖ¶ÔÓÚÈ«¾ÖµÄÈÏÖ¤¹Ü¿Ø

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews()
                .AddMvcOptions(options => { options.Filters.Add(new AuthorizeFilter()); });
    
        }
    }
    

    ´Ëʱ£¬¶ÔÓÚһЩ²»ÐèÒª½øÐÐÈÏÖ¤¾Í¿ÉÒÔ·ÃÎʵÄÒ³Ã棬ֻÐèÒªÌí¼Ó AllowAnonymous ÌØÐÔ¼´¿É

    public class AuthenticationController : Controller
    {
        [AllowAnonymous]
        public IActionResult Login()
        {
            return View();
        }
    }
    

    2.2¡¢ÅäÖÃÈÏÖ¤²ßÂÔ

    µ±È»£¬Èç¹ûÖ»ÊÇÕâÑùÐ޸ĵĻ°£¬ÆäʵÊÇÓÐÎÊÌâµÄ£¬¿ÉÒÔ¿´µ½£¬µ±Ìí¼ÓÉÏÈ«¾Ö¹ýÂËÆ÷ºó£¬ÏµÍ³ÒѾ­ÎÞ·¨Õý³£µÄ½øÐзÃÎÊ

    ÆôÓÃÊÚȨÖмä¼þ

    ¶ÔÓÚ authorization£¨ÊÚȨ£© À´Ëµ£¬ËüÆäʵÊÇÔÚ authentication£¨ÈÏÖ¤£©Í¨¹ýÖ®ºó²Å»á½øÐеIJÙ×÷£¬Ò²¾ÍÊÇ˵ÕâÀïÎÒÃÇȱÉÙÁ˶ÔÓÚϵͳÈÏÖ¤µÄÅäÖã¬ÒÀ¾Ý±¨´íÐÅÏ¢µÄÌáʾ£¬ÎÒÃÇÊ×ÏÈÐèҪͨ¹ýʹÓà AddAuthentication ·½·¨À´¶¨ÒåϵͳµÄÈÏÖ¤²ßÂÔ

    ÈÏÖ¤²ßÂÔ

    AddAuthentication ·½·¨Î»ÓÚ Microsoft.AspNetCore.Authentication Àà¿âÖУ¬Í¨¹ýÔÚ Nuget ÖÐËÑË÷¾Í¿ÉÒÔ·¢ÏÖ£¬.NET Core ÒѾ­»ùÓÚÒµ½çͨÓõĹ淶ʵÏÖÁ˶à¸öÈÏÖ¤²ßÂÔ

    ÒòΪÕâÀïʹÓÃµÄ Cookie ÈÏÖ¤ÒѾ­°üº¬ÔÚĬÈϵÄÏîÄ¿Ä£°åÖÐÁË£¬ËùÒԾͲ»ÐèÒªÔÙÒýÓÃÁË

    Ìí¼ÓÈÏÖ¤·þÎñ

    »ùÓÚ .NET Core ±ê×¼µÄ·þÎñʹÓÃÁ÷³Ì£¬Ê×ÏÈ£¬ÎÒÃÇÐèÒªÔÚ Startup.ConfigureServices ·½·¨À´ÖÐͨ¹ý AddAuthentication À´¶¨ÒåÕû¸öϵͳËùʹÓõÄÒ»¸öÊÚȨ²ßÂÔ£¬ÒÔ¼°£¬»ùÓÚÎÒÃDzÉÓà Cookie ÊÚȨµÄ·½Ê½£¬½áºÏÄ¿Ç°»¥ÁªÍøÕë¶Ô¿çÕ¾µãÇëÇóαÔì (CSRF) ¹¥»÷µÄ·À·¶ÒªÇó£¬ÎÒÃÇÐèÒª¶ÔÍøÕ¾µÄ Cookie ½øÐÐһЩÉ趨

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // ¶¨ÒåÊÚȨ²ßÂÔ
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    // ÎÞȨ·ÃÎʵÄҳ·¾¶
                    options.AccessDeniedPath = new PathString("/permission/forbidden");
    
                    // µÇ¼·¾¶
                    options.LoginPath = new PathString("/authentication/login");
    
                    // µÇ³ö·¾¶
                    options.LogoutPath = new PathString("/authentication/logout");
    
                    // Cookie ¹ýÆÚʱ¼ä(20 ·ÖÖÓ)
                    options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
                });
    
            // ÅäÖà Cookie ²ßÂÔ
            services.Configure<CookiePolicyOptions>(options =>
            {
                // ĬÈÏÓû§Í¬Òâ·Ç±ØÒªµÄ Cookie
                options.CheckConsentNeeded = context => true;
    
                // ¶¨Òå SameSite ²ßÂÔ£¬CookiesÔÊÐíÓ붥¼¶µ¼º½Ò»Æð·¢ËÍ
                options.MinimumSameSitePolicy = SameSiteMode.Lax;
            });
        }
    }
    

    Èç´úÂëËùʾ£¬ÔÚ¶¨ÒåÊÚȨ²ßÂÔʱ£¬ÎÒÃǶ¨ÒåÁËÈý¸öÖض¨ÏòµÄÒ³Ã棬ȥ¸æËß Cookie ÊÚȨ²ßÂÔÕâÀï¶ÔÓ¦µÄÒ³ÃæÔں䦣¬Í¬Ê±£¬ÒòΪÉí·ÝÑéÖ¤ Cookie µÄĬÈϹýÆÚʱ¼ä»á³ÖÐøµ½¹Ø±Õä¯ÀÀÆ÷Ϊֹ£¬Ò²¾ÍÊÇ˵£¬Ö»ÒªÓû§²»µã»÷Í˳ö°´Å¥²¢ÇÒ²»¹Ø±Õä¯ÀÀÆ÷£¬Óû§»áÒ»Ö±´¦ÓÚÒѾ­µÇ¼µÄ״̬£¬ËùÒÔÕâÀïÎÒÃÇÉ趨 20 ·ÖÖӵĹýÆÚʱ¼ä£¬±ÜÃâһЩ²»±ØÒªµÄ·çÏÕ

    ÖÁ´Ë£¬¶ÔÓÚ Cookie ÈÏÖ¤²ßÂÔµÄÅäÖþÍÍê³ÉÁË£¬ÏÖÔھͿÉÒÔÔÚ Startup.Configure ·½·¨ÖÐÌí¼Ó UseAuthentication Öмä¼þµ½ HTTP ¹ÜµÀÖУ¬ÊµÏÖ¶ÔÓÚÍøÕ¾ÈÏÖ¤µÄÆôÓã¬ÕâÀïÐèҪעÒ⣬ÒòΪÊÇÏÈÈÏÖ¤ÔÙÊÚȨ£¬ËùÒÔÖмä¼þµÄÌí¼Ó˳Ðò²»¿ÉÒԵߵ¹

    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
    
            // Ìí¼ÓÈÏÖ¤ÊÚȨ£¨Ë³Ðò²»¿ÉÒԵߵ¹£©
            //
            app.UseAuthentication();
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    "default",
                    "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
    

    ´Ëʱ£¬µ±ÎÒÃÇÔٴηÃÎÊϵͳʱ£¬ÒòΪûÓо­¹ýÈÏÖ¤£¬×Ô¶¯´¥·¢ÁËÖض¨Ïòµ½ÏµÍ³µÇ¼ҳÃæµÄ²Ù×÷£¬¶øÕâÀïÖض¨ÏòÌøתµÄÒ³Ãæ¾ÍÊÇÉÏÎÄ´úÂëÖÐÅäÖÃµÄ LoginPath µÄÊôÐÔÖµ

    µÇ¼Öض¨Ïò

    2.3¡¢µÇ¼¡¢µÇ³öʵÏÖ

    µ±ÈÏÖ¤²ßÂÔÅäÖÃÍê³ÉÖ®ºó£¬¾Í¿ÉÒÔ»ùÓÚÑ¡ÔñµÄ²ßÂÔÀ´½øÐеǼ¹¦ÄܵÄʵÏÖ¡£ÕâÀïµÄµÇ¼ҳÃæÉϵİ´Å¥£¬Ä£ÄâÁËÒ»¸öµÇ¼±íµ¥Ìá½»£¬µ±µã»÷Ö®ºó»á´¥·¢ÏµÍ³µÄÈÏÖ¤Âß¼­£¬ÊµÏÖ´úÂëÈçÏÂËùʾ¡£ÕâÀï±ðÍüÁ˽«µÇ¼Ê¼þµÄ Action ÉϼÓÉÏ AllowAnonymous ÌØÐÔ´Ó¶øÔÊÐíÄäÃû·ÃÎÊ

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> LoginAsync()
    {
        // 1¡¢Todo:УÑéÕË»§¡¢ÃÜÂëÊÇ·ñÕýÈ·£¬»ñÈ¡ÐèÒªµÄÓû§ÐÅÏ¢
    
        // 2¡¢´´½¨Óû§ÉùÃ÷ÐÅÏ¢
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, "ÕÅÈý"),
            new Claim(ClaimTypes.MobilePhone, "13912345678")
        };
    
        // 3¡¢´´½¨ÉùÃ÷Éí·ÝÖ¤
        var claimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
    
        // 4¡¢´´½¨ÉùÃ÷Éí·ÝÖ¤µÄ³ÖÓÐÕß
        var claimPrincipal = new ClaimsPrincipal(claimIdentity);
    
        // 5¡¢µÇ¼
        await HttpContext.SignInAsync(claimPrincipal);
    
        return Redirect("/");
    }
    

    ÔÚÕû¿éµÄ´úÂëÖУ¬Éæ¼°µ½Èý¸öÖ÷ÒªµÄ¶ÔÏó£¬Claim¡¢ClaimsIdentity ºÍ ClaimsPrincipal£¬Í¨¹ý¶ÔÓÚÕâÈý¸ö¶ÔÏóµÄʹÓ㬴ӶøʵÏÖ½«Óû§µÇ¼³É¹¦ºóϵͳËùÐèµÄÓû§ÐÅÏ¢°üº¬ÔÚ Cookie ÖÐ

    Èý¸ö¶ÔÏóÖ®¼äµÄÇø±ð£¬½èÓÃÀí½âASP.NET CoreÑé֤ģÐÍ(Claim, ClaimsIdentity, ClaimsPrincipal)²»µÃ²»¶ÁµÄÓ¢ÎIJ©ÎÄÕâƪ²©¿ÍµÄ½âÊÍÀ´ËµÃ÷

    • Claim£º±»ÑéÖ¤Ö÷ÌåÌØÕ÷µÄÒ»ÖÖ±íÊö£¬±ÈÈ磺µÇ¼Óû§ÃûÊÇ...£¬emailÊÇ...£¬Óû§IdÊÇ...£¬ÆäÖеġ°µÇ¼Óû§Ãû¡±£¬¡°email¡±£¬¡°Óû§Id¡±¾ÍÊÇ ClaimType
    • ClaimsIdentity£ºÒ»×é claims ¹¹³ÉÁËÒ»¸ö identity£¬¾ßÓÐÕâЩ claims µÄ identity ¾ÍÊÇ ClaimsIdentity £¬¼ÝÕÕ¾ÍÊÇÒ»ÖÖ ClaimsIdentity£¬¿ÉÒÔ°Ñ ClaimsIdentityÀí½âΪ¡°Ö¤¼þ¡±£¬¼ÝÕÕÊÇÒ»ÖÖÖ¤¼þ£¬»¤ÕÕÒ²ÊÇÒ»ÖÖÖ¤¼þ
    • ClaimsPrincipal£ºClaimsIdentity µÄ³ÖÓÐÕß¾ÍÊÇ ClaimsPrincipal £¬Ò»¸ö ClaimsPrincipal ¿ÉÒÔ³ÖÓжà¸ö ClaimsIdentity£¬¾Í±ÈÈçÒ»¸öÈ˼ȳÖÓмÝÕÕ£¬ÓÖ³ÖÓл¤ÕÕ

    ×îºó£¬Í¨¹ýµ÷Óà HttpContext.SignInAsync ·½·¨¾Í¿ÉÒÔÍê³ÉµÇ¼¹¦ÄÜ£¬¿ÉÒÔ¿´µ½£¬µ± Cookie ±»Çå³ýºó£¬Óû§Ò²¾Í´¦ÓڵdzöµÄ״̬ÁË£¬µ±È»£¬ÎÒÃÇÒ²¿ÉÒÔͨ¹ýÊÖ¶¯µÄµ÷Óà HttpContext.SignOutAsync À´ÊµÏֵdzö

    µÇ¼ʵÏÖ

    2.4¡¢»ñÈ¡Óû§ÐÅÏ¢

    ¶ÔÓÚÌí¼ÓÔÚ Claim ÖеÄÐÅÏ¢£¬ÎÒÃÇ¿ÉÒÔͨ¹ýÖ¸¶¨ ClaimType µÄ·½Ê½»ñÈ¡µ½£¬ÔÚ View ºÍ Controller ÖУ¬ÎÒÃÇ¿ÉÒÔÖ±½Óͨ¹ýÏÂÃæµÄ·½Ê½½øÐлñÈ¡£¬ÕâÀïʹÓõ½µÄ User Æäʵ¾ÍÊÇÉÏÎÄÖÐÌáµ½µÄ ClaimsPrincipal

    var userName = User.FindFirst(ClaimTypes.Name)?.Value;
    

    User ¶ÔÏó

    ¶øµ±ÎÒÃÇÐèÒªÔÚÒ»¸ö¶ÀÁ¢µÄÀà¿âÖлñÈ¡´æ´¢µÄÓû§ÐÅϢʱ£¬ÎÒÃÇÐèÒª½øÐÐÈçϵIJÙ×÷

    µÚÒ»²½£¬ÔÚ Startup.ConfigureServices ·½·¨ÖÐ×¢Èë HttpContextAccessor ·þÎñ

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // ×¢Èë HttpContext
            services.AddHttpContextAccessor();
    
        }
    }
    

    µÚ¶þ²½£¬ÔÚÄãÐèҪʹÓõÄÀà¿âÖÐͨ¹ý Nuget ÒýÓà Microsoft.AspNetCore.Http£¬Ö®ºó¾Í¿ÉÒÔÔÚ¾ßÌåµÄÀàÖÐͨ¹ý×¢Èë IHttpContextAccessor À´»ñÈ¡µ½Óû§ÐÅÏ¢£¬µ±È»£¬Ò²¿ÉÒÔÔÚ´Ë´¦ÊµÏֵǼ¡¢µÇ³öµÄ·½·¨

    namespace Sample.Infrastructure
    {
        public interface ICurrentUser
        {
            string UserName { get; }
    
            Task SignInAsync(ClaimsPrincipal principal);
    
            Task SignOutAsync();
    
            Task SignOutAsync(string scheme);
        }
    
        public class CurrentUser : ICurrentUser
        {
            private readonly IHttpContextAccessor _httpContextAccessor;
    
            private HttpContext HttpContext => _httpContextAccessor.HttpContext;
    
            public CurrentUser(IHttpContextAccessor httpContextAccessor)
            {
                _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
            }
    
            public string UserName => HttpContext.User.FindFirst(ClaimTypes.Name)?.Value;
    
            public Task SignInAsync(ClaimsPrincipal principal) => HttpContext.SignInAsync(principal);
    
            public Task SignOutAsync() => HttpContext.SignOutAsync();
    
            public Task SignOutAsync(string scheme) => HttpContext.SignOutAsync(scheme);
        }
    }
    

    ÖÁ´Ë£¬Õû¿éµÄÈÏÖ¤¹¦ÄܾÍÒѾ­ÊµÏÖÁË£¬Ï£Íû¶ÔÄãÓÐËù°ïÖú

    Reference

    1. SameSite cookies
    2. Work with SameSite cookies in ASP.NET Core
    3. What does the CookieAuthenticationOptions.LogoutPath property do in ASP.NET Core 2.1?
    4. Àí½âASP.NET CoreÑé֤ģÐÍ(Claim, ClaimsIdentity, ClaimsPrincipal)²»µÃ²»¶ÁµÄÓ¢ÎIJ©ÎÄ
    5. Introduction to Authentication with ASP.NET Core
    bk