Cookie-based認證明現

(使用ASP.NET 4.X 中的時候必定都用過Forms認證即FormsAuthentication作登陸用戶的身份認證,FormsAuthentication的核心就是Cookie,ASP.NET會將用戶名存儲在Cookie中。可是它很難進行擴展,更沒法與第三方認證集成,所以,在 ASP.NET Core 中對認證與受權進行了全新的設計,並使用基於聲明的認證(claims-based authentication))數組

1、新建項目初始化工做

在Controllers文件夾下新建AdminController.cs

設置視圖

@{
    ViewData["Title"] = "Admin";
}
<h2>@ViewData["Title"]</h2>

<p>Admin Page</p>

運行展現:

2、Cookie-based認證明踐

一、給AdminController添加 [Authorize] 標籤

提示讓咱們引用該空間便可。

二、在Startup方法中進行cookie的依賴注入

ConfigureServices方法下添加

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)  
.AddCookie(options=>{//自定義登錄地址,不配置的話則默認爲http://localhost:5000/Account/Login  
options.LoginPath="/Account/MyLogin";  
});  

提示讓咱們引用該空間便可。

 而後要在Configure方法中把cookie中間件也添加進來,不然認證受權是不會生效的

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();

            //注意app.UseAuthentication方法必定要放在下面的app.UseMvc方法前面,否者後面就算調用HttpContext.SignInAsync進行用戶登陸後,使用
            //HttpContext.User仍是會顯示用戶沒有登陸,而且HttpContext.User.Claims讀取不到登陸用戶的任何信息。
            //這說明Asp.Net OWIN框架中MiddleWare的調用順序會對系統功能產生很大的影響,各個MiddleWare的調用順序必定不能反
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

這裏順便說一下app.UseAuthentication是用來幹什麼的,app.UseAuthentication會啓用Authentication中間件,該中間件會根據當前Http請求中的Cookie信息來設置HttpContext.User屬性(後面會用到),因此只有在app.UseAuthentication方法以後註冊的中間件纔可以從HttpContext.User中讀取到值,這也是爲何上面強調app.UseAuthentication方法必定要放在下面的app.UseMvc方法前面,由於只有這樣ASP.NET Core的MVC中間件中才能讀取到HttpContext.User的值。瀏覽器

發現已經自動跳轉到登錄地址了。

 三、模擬登錄

 暫時不作登錄的,只是模擬一下登錄,首先建立一個AccountController.cs

添加兩個API用於登錄和登出

    public class AccountController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
        //登錄
        public IActionResult MakeLogin()
        {
            var claims = new List<Claim>(){
                new Claim(ClaimTypes.Name,"wangyuting"),
                new Claim(ClaimTypes.Role,"admin")
            };
            //必需要加CookieAuthenticationDefaults.AuthenticationScheme,否則沒法解析
            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

            HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
            return Ok();
        }
        //登出
        public IActionResult Logout()
        {
            HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

            return Ok();
        }

    }

 

 

在ASP.NET CORE中使用Cookie認證登陸用戶的方法和傳統的FormsAuthentication不太同樣,大體步驟以下:cookie

  • 建立Claim類型的數組,將登陸用戶的全部信息(好比用戶名)存儲在Claim類型的字符串鍵值對中
  • 將上面建立的Claim類型的數組傳入ClaimsIdentity中,用來構造一個ClaimsIdentity對象
  • 將上面建立的ClaimsIdentity對象傳入ClaimsPrincipal中,用來構造一個ClaimsPrincipal對象
  • 調用HttpContext.SignInAsync方法,傳入上面建立的ClaimsPrincipal對象,完成用戶登陸

因此咱們能夠看到整個ASP.NET CORE的Cookie認證登陸流程比之前ASP.NET的FormsAuthentication仍是要複雜許多,畢竟之前一個FormsAuthentication.SetAuthCookie方法就搞定了。app

 

在本文的例子中咱們在項目中默認的HomeController中建立了一個Acion方法Login,來實現用戶登陸的代碼。固然這裏咱們實現的是最簡的Cookie登陸,下面代碼中實際上還能夠設置Cookie是否持久化、Cookie多久過時、存儲登陸用戶信息的Cookie的名字是什麼等,咱們就不作過多介紹了,你們能夠閱讀本文最後推薦的兩份官方文檔瞭解更多。框架

Login方法的代碼以下:

/// <summary>
/// 該Action登陸用戶Wangdacui到Asp.Net Core
/// </summary>
public IActionResult Login()
{
    //下面的變量claims是Claim類型的數組,Claim是string類型的鍵值對,因此claims數組中能夠存儲任意個和用戶有關的信息,
    //不過要注意這些信息都是加密後存儲在客戶端瀏覽器cookie中的,因此最好不要存儲太多特別敏感的信息,這裏咱們只存儲了用戶名到claims數組,
    //表示當前登陸的用戶是誰
    var claims = new[] { new Claim("UserName", "Wangdacui") };

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

    ClaimsPrincipal user = new ClaimsPrincipal(claimsIdentity);

    Task.Run(async () =>
    {
        //登陸用戶,至關於ASP.NET中的FormsAuthentication.SetAuthCookie
        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);

        //可使用HttpContext.SignInAsync方法的重載來定義持久化cookie存儲用戶認證信息,例以下面的代碼就定義了用戶登陸後60分鐘內cookie都會保留在客戶端計算機硬盤上,
        //即使用戶關閉了瀏覽器,60分鐘內再次訪問站點仍然是處於登陸狀態,除非調用Logout方法註銷登陸。
        //注意其中的AllowRefresh屬性,若是AllowRefresh爲true,表示若是用戶登陸後在超過50%的ExpiresUtc時間間隔內又訪問了站點,就延長用戶的登陸時間(其實就是延長cookie在客戶端計算機硬盤上的保留時間),
        //例如本例中咱們下面設置了ExpiresUtc屬性爲60分鐘後,那麼當用戶登陸後在大於30分鐘且小於60分鐘內訪問了站點,那麼就將用戶登陸狀態再延長到當前時間後的60分鐘。可是用戶在登陸後的30分鐘內訪問站點是不會延長登陸時間的,
        //由於ASP.NET Core有個硬性要求,是用戶在超過50%的ExpiresUtc時間間隔內又訪問了站點,才延長用戶的登陸時間。
        //若是AllowRefresh爲false,表示用戶登陸後60分鐘內無論有沒有訪問站點,只要60分鐘到了,立馬就處於非登陸狀態(不延長cookie在客戶端計算機硬盤上的保留時間,60分鐘到了客戶端計算機就自動刪除cookie)
        /*
        await HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme,
        user, new AuthenticationProperties()
        {
            IsPersistent = true,
            ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60),
            AllowRefresh = true
        });
        */

    }).Wait();

    return View();
}

若是當前Http請求原本登陸了用戶A,如今調用HttpContext.SignInAsync方法登陸用戶B,那麼至關於註銷用戶A,登陸用戶Basync

3.讀取登陸用戶信息ui

那麼用戶登陸後怎麼將登陸用戶的信息(好比用戶名)讀取出來呢?咱們在HomeController的Index方法中演示瞭如何判斷當前用戶是否已經登陸,而且讀出登陸用戶的用戶名,Index方法的代碼以下所示:加密

/// <summary>
/// 該Action判斷用戶是否已經登陸,若是已經登陸,那麼讀取登陸用戶的用戶名
/// </summary>
public IActionResult Index()
{
    //若是HttpContext.User.Identity.IsAuthenticated爲true,
    //或者HttpContext.User.Claims.Count()大於0表示用戶已經登陸
    if (HttpContext.User.Identity.IsAuthenticated)
    {
        //這裏經過 HttpContext.User.Claims 能夠將咱們在Login這個Action中存儲到cookie中的全部
        //claims鍵值對都讀出來,好比咱們剛纔定義的UserName的值Wangdacui就在這裏讀取出來了
        var userName = HttpContext.User.Claims.First().Value;
    }

    return View();
}

注意,最好仍是用HttpContext.User.Identity.IsAuthenticated來判斷用戶是否已經登陸spa

註銷用戶設計

那麼登陸用戶後怎麼註銷登陸呢?咱們在HomeController的Logout方法中演示瞭如何註銷登陸的用戶,代碼以下所示:

/// <summary>
/// 該Action從Asp.Net Core中註銷登陸的用戶
/// </summary>
public IActionResult Logout()
{
    Task.Run(async () =>
    {
        //註銷登陸的用戶,至關於ASP.NET中的FormsAuthentication.SignOut  
        await HttpContext.SignOutAsync();
    }).Wait();

    return View();
}

果當前Http請求原本就沒有登陸用戶,那麼調用HttpContext.SignOutAsync方法時也不會報錯

相關文章
相關標籤/搜索