2018年4月16日 星期一

JWT JSON Web Token 使用 ASP.NET Core 2.0 Web API 的逐步練習教學與各種情境測試

至於要如何在使用端 Client 來進行使用者身分驗證,並且取得 JWT Token 權杖,接著使用該權杖來呼叫其他 Web API 的方法,可以參考 使用 HttpClient 進行 JWT 身分驗證與呼叫需要授權的 API 和重新更新 Token 權杖的程式設計範例 ;在這篇文章中,也包含了如何在用戶端進行更新 JWT Token 的作法。

在這篇文章中,我們將來體驗如何使用 ASP.NET Core 2.0 專案,搭配 JWT 機制,設計出具有存取權杖 Token 基礎的 Web API 服務。

了解更多關於 [ASP.NET Core 簡介
了解更多關於 [在 ASP.NET 4.x 和 ASP.NET Core 之間進行選擇]  



首先,您需要了解甚麼叫做 JSON Web Token (JWT),在 RFC 7519 文件中,有詳細與明確的定義,各位可以從這裡了解到甚麼叫做 JWT 與其相關資料結構與組成成員。另外,在這個 jwt.io 網頁中,您可以找到各種 JWT 的工具與程式庫和更多的解釋說明,例如,您可以快速瀏覽這篇 JWT 簡介 文章,快速了解到何謂 JWT與如何使用它。
由於我們使用的是 ASP.NET Core 2.0 Web API 方式來進行說明如何建置出一個 JWT 存取權杖 Access Token 的應用,因此,您需要對於 ASP.NET Core 2.0 有所認識,若您對於 ASP.NET Core 2.0 還沒接觸過,您可以參考 ASP.NET Core 2.0 使用者入門 這個網頁上的相關介紹內容與知識。另外,您的開發工具也需要準備好,您需要安裝 .NET Core 2.0.0 或更新版本,在您的 Visual Studio Installer 工具中,確認已經升級到最新的 Visual Studio2017 15.6.1 版本(這個版本是寫這篇文章時候的最新版本)或更新版本,加上下列工作負載需要勾選 [ASP.NET 與網頁程式開發] & [.NET Core 跨平台開發]。
Visual Studio 2017 About
本篇文章的專案範例原始碼,可以從 https://github.com/vulcanlee/CSharpNotes2018/tree/master/CoreJWT取得

建立一個 ASP.NET Core 2.0 Web API 專案

現在,讓我們開始進行建立一個 ASP.NET Core 2.0 Web API 專案
  • 點選 Visual Studio 2017 功能表 [檔案] > [新增] > [專案]
  • 當出現 [新增專案] 對話窗,點選 [已安裝] > [Visual C#] > [.NET Core] > [ASP.NET Core Web 應用程式],並且在最下方 [名稱] 欄位處,輸入 CoreJWT,作為此練習的開發專案名稱。
    Visual Studio 2017 新增專案對話窗
  • 當出現了 [新增 ASP.NET Core Web API 應用程式 - CoreJWT] 對話窗,請點選 [API] 項目,確認該對話窗的右方的 [驗證] 設定值為 [無驗證],如同下方螢幕截圖相同,就可以點選右下角的 [確定] 按鈕。
    新增 ASP.NET Core Web API 應用程式 - CoreJWT對話窗
  • 稍微等候一下,我們可以看到這個 ASP.NET Core 2.0 Web API 專案已經建立完成,並且從 Visual Studio 2017 方案總管中,您將會看到如同下面螢幕截圖,這裡就是這個 Web API 專案的所有檔案結構。
    Visual Studio 2017 ASP.NET Web API 方案專案結構
  • 最後,讓我們實際建置、執行這個專案,您就會在瀏覽器上看到 ["value1","value2"] 這樣的輸出結果。
    Web API 專案執行結果

修正 Startup 類別的運作行為

  • 我們先要定義 JWT Token 存取權杖會用到的定義字串,所以,請在專案中找到 appsettings.json 檔案,將它打開來,並且將這個檔案內容下改成為如下所示。
    在這裡,我們可以看到,我們新增了 Tokens 這個節點,裡面有三個子節點,這三個定義字串,我們將會等下會用到。
JSON
{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "Tokens": {
    "ValidIssuer": "CoreJWT.vulcan.net",
    "ValidAudience": "Xamarin RESTful API",
    "IssuerSigningKey": "4{!-!Rjx2.W]fX~jN:<Ae$D'dLlnG%%xo`W2D5TatBx&MJjZ>(+ujy*G*Y<XH.X"
  }
}
  • 在專案中,找到 [Startup.cs] 檔案,將其打開,您將會看到這個 Startup 類別的定義,在這個 Startup 類別中,您也會看到 public void ConfigureServices(IServiceCollection services) 這個方法與 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 這個方法,我們等下就要來修正這兩個方法內的定義程式碼。
C Sharp / C#
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}
  • 請在 Starpup.cs 檔案內,加入底下命名空間參考
C Sharp / C#
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System.Diagnostics;
  • 請使用底下程式碼,將 Starpup 類別定義程式碼,改成底下的類別定義程式碼
C Sharp / C#
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration["Tokens:ValidIssuer"],
                    ValidAudience = Configuration["Tokens:ValidAudience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:IssuerSigningKey"])),
                    RequireExpirationTime = true,
                };
                options.Events = new JwtBearerEvents()
                {
                    OnAuthenticationFailed = context =>
                    {
                        context.NoResult();

                        context.Response.StatusCode = 401;
                        context.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = context.Exception.Message;
                        Debug.WriteLine("OnAuthenticationFailed: " + context.Exception.Message);
                        return Task.CompletedTask;
                    },
                    OnTokenValidated = context =>
                    {
                        Console.WriteLine("OnTokenValidated: " +
                            context.SecurityToken);
                        return Task.CompletedTask;
                    }

                };
            });

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseAuthentication();

        app.UseMvc();
    }
}
  • 想要讓這個 Web API 專案可以套用 JWT Bearer 驗證,我們需要先在 Configure 方法內,呼叫 app.UseAuthentication(); 方法。
  • 接著,我們需要在 ConfigureServices 方法內,叫用AddJwtBearer方法中的ConfigureServices方法。
    在 AddJwtBearer 方法內,需要設定 JwtBearerOptions.TokenValidationParameters 屬性,因此,我們建立一個 TokenValidationParameters 物件 Object / 執行個體 Instance ,並且設定這個 JWT Token 存取權杖會用到的相關屬性值。
  • 我們也訂閱了 JwtBearerOptions.Events 的 相關事件,在這裡,我們透過建立了 JwtBearerEvents 物件,並且設定相關事件的委派方法。我們綁定了 OnAuthenticationFailed 這個事件,也就是當所傳入的存取權杖不是正確的、合法的、有效的,此時,就會呼叫這個委派事件的方法,在這個方法哩,將會回傳 401 狀態碼 Status Code,說明此次身分驗證結果是失敗的。反之,OnTokenValidated 這個委派事件的方法,將會被呼叫。

建立控制器 Controller 與動作 Action

  • 現在,我們需要來建立控制器與相關方法,並且接下來的檢驗各種不同的使用情境下,我們的 Web API 會產生甚麼樣的結果。
  • 首先,滑鼠右擊專案的 Controllers 目錄,選擇 [加入] > [控制器]
  • 當出現 [新增 Scaffold] 對話窗,請選擇 [執行讀取/寫入動作的 API 控制器],並且點選 [新增] 按鈕
    Visual Studio 2017 新增 Scaffold 對話窗
  • 當出現了 [新增 執行讀取/寫入動作的 API 控制器] 對話窗,請在控制器名稱欄位內,輸入 JWTToken,最後點選 [新增]
    新增 執行讀取/寫入動作的 API 控制器 對話窗
  • 接著,滑鼠右擊專案的 Controllers 目錄,選擇 [加入] > [控制器]
  • 當出現 [新增 Scaffold] 對話窗,請選擇 [執行讀取/寫入動作的 API 控制器],並且點選 [新增] 按鈕
    Visual Studio 2017 新增 Scaffold 對話窗
  • 當出現了 [新增 執行讀取/寫入動作的 API 控制器] 對話窗,請在控制器名稱欄位內,輸入 Login ,最後點選 [新增]
    新增 執行讀取/寫入動作的 API 控制器 對話窗
  • 請使用底下程式碼,取代 LoginController.cs 的所有內容
    在 LoginController 控制器中,若使用 HTTP GET 方法,會取得一個 JWT 存取權杖 Access Token,這個存取權杖將會擁有 7 天的有效期限。若使用 HTTP POST 方法,會取得一個 JWT 存取權杖 Access Token,這個存取權杖將會擁有 1 分鐘的有效期限。
C Sharp / C#
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;

namespace CoreJWT.Controllers
{
    [Produces("application/json")]
    [Route("api/Login")]
    public class LoginController : Controller
    {
        public IConfiguration Configuration { get; }
        public LoginController(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.NameId, "vulcan.lee@vulcan.net"),
                new Claim(ClaimTypes.Role, "Admini"),
            };

            var token = new JwtSecurityToken
            (
                issuer: Configuration["Tokens:ValidIssuer"],
                audience: Configuration["Tokens:ValidAudience"],
                claims: claims,
                expires: DateTime.UtcNow.AddDays(7),
                signingCredentials: new SigningCredentials(new SymmetricSecurityKey
                (Encoding.UTF8.GetBytes(Configuration["Tokens:IssuerSigningKey"])),
                SecurityAlgorithms.HmacSha256)
            );

            return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
        }

        // POST: api/Login
        [HttpPost]
        public async Task<IActionResult> Post()
        {
            var claims = new[]
      {
                new Claim(JwtRegisteredClaimNames.NameId, "vulcan.lee@vulcan.net"),
                new Claim(ClaimTypes.Role, "Admini"),
            };

            var token = new JwtSecurityToken
            (
                issuer: Configuration["Tokens:ValidIssuer"],
                audience: Configuration["Tokens:ValidAudience"],
                claims: claims,
                expires: DateTime.UtcNow.AddMinutes(1),
                signingCredentials: new SigningCredentials(new SymmetricSecurityKey
                            (Encoding.UTF8.GetBytes(Configuration["Tokens:IssuerSigningKey"])),
                        SecurityAlgorithms.HmacSha256)
            );

            return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
        }
    }
}
  • 請使用底下程式碼,取代 JWTTokenController.cs 的所有內容
    在這個 JWTTokenController 控制器中
    • HTTP GET 動作
      無須傳送任任何存取權杖,就可以直接呼叫
    • HTTP PUT 動作
      因為這個動作方法上,有使用 Authorize 標示,所以,當使用 PUT 動作呼叫這個 Web API 的時候,需要傳入一個存取權杖才能夠呼叫。
    • HTTP POST 動作
      因為這個動作方法上,有使用 Authorize(Roles = "Admin") 標示,所以,當使用 POST 動作呼叫這個 Web API 的時候,需要傳入一個存取權杖才能夠呼叫,而且這個存取權杖中,需要擁有 Admin 這個 Roles。我們可以從 Login 控制器的 GET 或者 POST 動作方法中得知,我們所取得的存取權杖,僅具有 new Claim(ClaimTypes.Role, "Admini") 這樣的 Role,因此,呼叫這個動作將會失敗。
    • HTTP DELETE 動作
      因為這個動作方法上,有使用 Authorize(Roles = "Admini") 標示,所以,當使用 DELETE 動作呼叫這個 Web API 的時候,需要傳入一個存取權杖才能夠呼叫,而且這個存取權杖中,需要擁有 Admini 這個 Roles。我們可以從 Login 控制器的 GET 或者 POST 動作方法中得知,我們所取得的存取權杖,僅具有 new Claim(ClaimTypes.Role, "Admini") 這樣的 Role,因此,呼叫這個動作將會成功。
C Sharp / C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace CoreJWT.Controllers
{
    [Produces("application/json")]
    [Route("api/JWTToken")]
    public class JWTTokenController : Controller
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "JWTToken", "Get ( no Authorize )" };
        }

        [HttpPut]
        [Authorize]
        public IEnumerable<string> Put()
        {
            return new string[] { "JWTToken", "Put ( has Authorize)" };
        }

        [HttpPost]
        [Authorize(Roles = "Admin")]
        public IEnumerable<string> Post()
        {
            return new string[] { "JWTToken", "Post ( has Authorize and Roles=Admin )" };
        }

        [HttpDelete]
        [Authorize(Roles = "Admini")]
        public IEnumerable<string> Delete()
        {
            return new string[] { "JWTToken", "Post ( has Authorize and Roles=Admini )" };
        }
    }
}

進行 RESTfule Web API 的測試

最後,讓我們使用 PostMan 這個工具,開始進行我們剛剛寫好的 JWT 各種 Web API 來進行測試。現在,請開始執行這個專案。

取得具有 7 天有效期限的 Access Token 存取權杖

JSON
{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjEzODM2NDksImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.2w6BoAq_KbVlrVJW_ldrO5-cLuMPMp7uQ77tGKfakTA"
}
使用 HTTP GET 取得存取權杖
  • 打開 https://jwt.io/ 網頁,請剛剛取得的存取權杖(token的值,也就是 eyJ...TA 這段字串)複製下來,貼到網頁中的 Encoded 文字輸入盒中,會看到這個存取權杖的詳細內容。
    透過 Jwt.io 網頁,驗證 使用 HTTP GET 取得存取權杖

取得具有 1 分鐘有效期限的 Access Token 存取權杖

JSON
{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjA3NzkxNTAsImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.1iOWpcqtKyuFZ94ShA1XT1wctAbVzVN6daemUqScStU"
}
使用 HTTP POST 取得存取權杖
  • 打開 https://jwt.io/ 網頁,請剛剛取得的存取權杖(token的值,也就是 eyJ...StU 這段字串)複製下來,貼到網頁中的 Encoded 文字輸入盒中,會看到這個存取權杖的詳細內容。
    透過 Jwt.io 網頁,驗證 使用 HTTP GET 取得存取權杖

使用 GET 方法呼叫 JWTToken 控制器 Web API

使用 PUT 方法呼叫 JWTToken 控制器 Web API

  • 打開 PostMan
  • 設定使用 HTTP PUT 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,在這裡,我們看到了,此次呼叫,得到了 Status Code 狀態碼 401,也就是說失敗了,不過,這個 Web API 已經受到了保護,也就是說,若沒有提供正確的存取權杖,是無法正常呼叫與使用這個 Web API 的
    沒有用 Access Token 呼叫有標示 Authorize 的 Web API

使用具有 7 天有效期限的 Access Token 存取權杖與 GET 方法呼叫 JWTToken Web API

  • 打開 PostMan
  • 設定使用 HTTP GET 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [Header] 標籤頁次
  • 在 [Key] 欄位 輸入 Authorization
  • 在 [Value] 欄位 輸入 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjA3NzkxNTAsImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.1iOWpcqtKyuFZ94ShA1XT1wctAbVzVN6daemUqScStU
    其中,在 Bearer 之後的字串,是剛剛取得具有 7 天有效期限的 Access Token 存取權杖
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,在這裡,因為這個 GET 動作方法沒有受到保護,不管我們是否有使用 Authorization 標頭 Header,我們都可以正常使用這個 Web API
    沒有用 Access Token 呼叫有標示 Authorize 的 Web API

使用具有 1 分鐘有效期限的 Access Token 存取權杖與 GET 方法呼叫 JWTToken Web API

  • 打開 PostMan
  • 設定使用 HTTP GET 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [Header] 標籤頁次
  • 在 [Key] 欄位 輸入 Authorization
  • 在 [Value] 欄位 輸入 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjEzODM2NDksImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.2w6BoAq_KbVlrVJW_ldrO5-cLuMPMp7uQ77tGKfakTA
    其中,在 Bearer 之後的字串,是剛剛取得具有 1 分鐘有效期限的 Access Token 存取權杖;在 JSON Web Token (JWT),在 RFC 7519 文件中有提到,雖然我們設定這個 Access Token 存取權杖有效時間只有1分鐘,不過,在後端伺服器實作上,還是會有些容許時間差,因此,建議您可以在取得這個存取權杖之後的 5~10分鐘後,再來使用這個存取權杖。
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,在這裡,因為這個 GET 動作方法沒有受到保護,不管我們是否有使用 Authorization 標頭 Header,我們都可以正常使用這個 Web API,但是,您會發現到,此時的回傳的 Status Code 狀態碼是 IDX10223: Lifetime validation failed. The token is expired. 。而且,它實際上還會有這樣的訊息,ValidTo: '03/11/2018 14:39:10' Current time: '03/11/2018 16:19:22'. 告知您,這個存取權杖已經真正逾期了。
    JWT Access Token PostMan Asp.net Core Web API

使用具有 7 天有效期限的 Access Token 存取權杖與 PUT 方法呼叫 JWTToken Web API

  • 打開 PostMan
  • 設定使用 HTTP PUT 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [Header] 標籤頁次
  • 在 [Key] 欄位 輸入 Authorization
  • 在 [Value] 欄位 輸入 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjA3NzkxNTAsImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.1iOWpcqtKyuFZ94ShA1XT1wctAbVzVN6daemUqScStU
    其中,在 Bearer 之後的字串,是剛剛取得具有 7 天有效期限的 Access Token 存取權杖
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,雖然 PUT 動作有受到 [Authorize] 屬性的保護,不過,我們有透過 HTTP 基本驗證協定,將 JWT Access Token 存取權杖傳送到伺服器端,而這個存取權杖是合法且有效的,因此,我們都可以正常使用這個 Web API
    JWT Access Token PostMan Asp.net Core Web API

使用具有 1 分鐘有效期限的 Access Token 存取權杖與 PUT 方法呼叫 JWTToken Web API

  • 打開 PostMan
  • 設定使用 HTTP PUT 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [Header] 標籤頁次
  • 在 [Key] 欄位 輸入 Authorization
  • 在 [Value] 欄位 輸入 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjEzODM2NDksImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.2w6BoAq_KbVlrVJW_ldrO5-cLuMPMp7uQ77tGKfakTA
    其中,在 Bearer 之後的字串,是剛剛取得具有 1 分鐘有效期限的 Access Token 存取權杖
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,在這裡,因為這個 PUT 動作方法有受到 [Authorize] 屬性的保護,因此,當我們使用了一個時間逾期的存取權杖,雖然它是合法、正確的權杖,但卻不是有效的,因此我們依然會得到回傳的 Status Code 狀態碼是 IDX10223: Lifetime validation failed. The token is expired. 。並且,我們看到回應結果的 Body 欄位,是沒有任何資料的,也就是這個 PUT 動作方法,是沒有成功呼叫的。
    JWT Access Token PostMan Asp.net Core Web API

使用具有 7 天有效期限的 Access Token 存取權杖與 POST 方法呼叫 JWTToken Web API

現在,我們使用具有 7 天有效期限的 Access Token 存取權杖,使用 POST 方法來呼叫 JWTToken Web API,可是,在這個 Web API 中,使用了 [Authorize(Roles = "Admin")] 屬性來保護這個 Web API,也就是說,這個存取權杖必須要具有 Admin 的 Role。
可是,在我們進行呼叫登入 Web API 的時候,每個存取權杖都會產生一個 Admini 這個 Claim,我們是使用這段程式碼 new Claim(ClaimTypes.Role, "Admini")。所以,原則上,我們的存取權杖雖然是正確的,但是因為沒有相同的 Role,所以,還是無法呼叫這個 Web API。
  • 打開 PostMan
  • 設定使用 HTTP POST 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [Header] 標籤頁次
  • 在 [Key] 欄位 輸入 Authorization
  • 在 [Value] 欄位 輸入 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjA3NzkxNTAsImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.1iOWpcqtKyuFZ94ShA1XT1wctAbVzVN6daemUqScStU
    其中,在 Bearer 之後的字串,是剛剛取得具有 7 天有效期限的 Access Token 存取權杖
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,根據在做這個測試的說明,我們得到了 403 Foribidden 這樣的錯誤狀態碼 Status Code,而且回應的 Body 也同樣的沒有回傳任何內容,也就是這個 POST 方法,是沒有被呼叫到。
    JWT Access Token PostMan Asp.net Core Web API

使用具有 7 天有效期限的 Access Token 存取權杖與 DELETE 方法呼叫 JWTToken Web API

現在,我們使用具有 7 天有效期限的 Access Token 存取權杖,使用 DELETE 方法來呼叫 JWTToken Web API,在這個 Web API 中,使用了 [Authorize(Roles = "Admini")] 屬性來保護這個 Web API,也就是說,這個存取權杖必須要具有 Admini 的 Role。
在我們進行呼叫登入 Web API 的時候,每個存取權杖都會產生一個 Admini 這個 Claim,我們是使用這段程式碼 new Claim(ClaimTypes.Role, "Admini")。所以,原則上,我們的存取權杖雖然是可以呼叫這個 Web API。
  • 打開 PostMan
  • 設定使用 HTTP DELETE 方法
  • 輸入網址為 http://localhost:50554/api/JWTToken
  • 點選 [Header] 標籤頁次
  • 在 [Key] 欄位 輸入 Authorization
  • 在 [Value] 欄位 輸入 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiJ2dWxjYW4ubGVlQHZ1bGNhbi5uZXQiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbmkiLCJleHAiOjE1MjA3NzkxNTAsImlzcyI6IkNvcmVKV1QudnVsY2FuLm5ldCIsImF1ZCI6IlhhbWFyaW4gUkVTVGZ1bCBBUEkifQ.1iOWpcqtKyuFZ94ShA1XT1wctAbVzVN6daemUqScStU
    其中,在 Bearer 之後的字串,是剛剛取得具有 7 天有效期限的 Access Token 存取權杖
  • 點選 [SEND] 按鈕
  • 我們將會得到底下的輸出結果,根據在做這個測試的說明,我們真的可以正常呼叫這個 Delete Web API,而且,可以得到回應結果內容。
    JWT Access Token PostMan Asp.net Core Web API

其他相關文章

更多關於 Xamarin / Xamarin.Forms 教學、技術分享、用法文章,請參考 I ♥ Xamarin

沒有留言:

張貼留言