.Net Core之JWT授權

SportSky發表於2022-03-02

一、什麼是JWT

文章參考:https://www.leo96.com/article/detail/55

JSON Web令牌(JWT)是一個開放標準(RFC 7519),它定義 了一種緊湊且自包含的方式,用於在各方之間安全地傳輸資訊作為JSON物件。由於此資訊是經過數字簽名的,因此可以被驗證和信任。可以使用祕密(使用HMAC演算法)或使用RSA或ECDSA的公鑰/私鑰對JWT進行簽名。

二、使用場景

1、授權:這是使用JWT的最常見方案。一旦使用者登入,每個後續請求將包括JWT,從而允許使用者訪問該令牌允許的路由,服務和資源。單一登入是當今廣泛使用JWT的一項功能,因為它的開銷很小並且可以在不同的域中輕鬆使用。

2、資訊交換:JSON Web令牌是在各方之間安全傳輸資訊的好方法。因為可以對JWT進行簽名(例如,使用公鑰/私鑰對),所以您可以確定發件人是他們所說的人。此外,由於簽名是使用標頭和有效負載計算的,因此您還可以驗證內容是否未被篡改。

三、JWT授權流程

四、JWT令牌結構

1、header(頭部)頭部是令牌的第一部分,通常由兩部分組成:令牌的型別(即JWT)和令牌所使用的簽名演算法,如SHA256、HMAC等

2、payload(有效載荷)頭部是令牌的第一部分,通常由兩部分組成:令牌的型別(即JWT)和令牌所使用的簽名演算法,如SHA256、HMAC等

有三種說明型別,預定義宣告、公共宣告和私有宣告。宣告名稱僅是三個字元,因為JWT是緊湊的

  • 預定義宣告:包括iss(發出者), exp(到期時間), sub(主題), aud(受眾)等,是推薦的但是不是強制的可以沒有。
  • 公共宣告:公共宣告,這個部分可以隨便定義,但是要注意和 IANA JSON Web Token 衝突。
  • 私有宣告:這個部分是共享被認定資訊中自定義部分。

3、signature(簽名)  簽名是令牌的第三部分,由header和payload進行64位編碼後再使用加密演算法加密即可

五、程式碼擼起來

樓主用vs2022新建了兩個解決方案,分別是Application.Authorization(用來生成token),Application.WebAPI(用來token授權)

 

 

一、生成token 

[ApiController]
    [Route("[controller]")]
    public class AuthorizationController : ControllerBase
    {
        public IConfiguration _configuration { get; }
        public AuthorizationController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        /// <summary>
        /// 獲取Token
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetToken")]
        public dynamic GetToken(string userName= "xiaohemaio", string pwd= "123456")
        {
            // 驗證使用者和密碼應該去查詢資料庫,此處省略
            if(userName.Equals("xiaohemaio") && pwd.Equals("123456"))
            {
                //  有效載荷,這裡可以自定義寫,儘量避免敏感資訊

                Claim[] claims = new Claim[] { 
                new Claim("NickName",userName),
                new Claim("Role","Admin")
                };
                // 需要加密,需要加密key
                // NuGet引入:Microsoft.IdentityModel.Tokens
                SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWTAuthorization:securitykey"]));

                SigningCredentials creds = new SigningCredentials(key,SecurityAlgorithms.HmacSha256);

                // NuGet引入:Microsoft.IdentityModel.Tokens.Jwt
                // 官方規定了7個非強制但建議使用的欄位:
                // iss(issuer):簽發人
                // exp(expiration time) :過期時間
                // sub(subject):主題
                // aud(audience):受眾
                // nbf(not befaore):生效時間
                // lat(issued at):簽發時間
                // jti(jwt id):編號

                JwtSecurityToken token = new JwtSecurityToken(
                issuer:_configuration["JWTAuthorization:issuer"],
                audience: _configuration["JWTAuthorization:audience"],
                claims: claims,
                expires:System.DateTime.Now.AddMinutes(5),
                signingCredentials: creds
                );

                string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
                return Ok(new { Data= returnToken ,Success=true,Msg="Token生成成功"});
            }
            return Ok(new { Data = string.Empty, Success = false, Msg = "Token生成失敗" });
        }
    }

 

  "JWTAuthorization": {
    "issuer": "xiaohemaio", // 簽發人,可自定義
    "audience": "xiaohemiao", // 受眾,可自定義
    "securitykey": "8cbe2b73be20b183bd787f31d4dc3f0d05bb2640495ebf8f52e790907d20f70a" // 加密key,根據需要自己生成 參考地址 https://crypot.51strive.com/sha256.html

  }

 

 

 

 二、Token授權

[ApiController]
    [Route("[controller]")]
    public class AuthorizationController : ControllerBase
    {

        [HttpGet]
        [Route("Get")]
        public dynamic Get()
        {
            return Ok(new { Data = "test", Sueccess = true });
        }

        [HttpGet]
        [Route("GetAuthorizationData")]
        [Authorize]
        public dynamic GetAuthorizationData()
        {
            // 獲取當前登入的使用者名稱
            var userName = HttpContext.AuthenticateAsync().Result.Principal.Claims.FirstOrDefault(x => x.Type.Equals("NickName"))?.Value;

            return new JsonResult(new { Data = userName, Sueccess = true });
        }

       
    }
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.AddControllers();

            {
                // ************************2、JWT鑑權授權******************************************
                // NuGet引入程式包:Microsoft.AspNetCore.Authentication.JwtBearer (如果是.net5則使用5.0及以上的版本,如是.net6 則使用6.0及以上版本,如是.net core 3.1 則使用3.0及以上版本)
                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options => {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey= true,
                            ValidIssuer= Configuration["JWTAuthorization:issuer"], // Issuer 這個和應用Application.Authorization裡面的設定一樣,表示誰簽發的Token
                            ValidAudience = Configuration["JWTAuthorization:audience"], // Audience 這個和應用Application.Authorization裡面的設定一樣,表示受眾的Token
                            IssuerSigningKey =new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWTAuthorization:securitykey"])), // 拿到securitykey 
                            AudienceValidator = (m,n,z) => {  // 自定義規則
                                return true;
                            }
                        };
                    });
            }


        }

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

            app.UseRouting();

            // ********************1、啟用鑑權*********************
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
  "JWTAuthorization": {
    "issuer": "xiaohemaio", // 簽發人,可自定義
    "audience": "xiaohemiao", // 受眾,可自定義
    "securitykey": "8cbe2b73be20b183bd787f31d4dc3f0d05bb2640495ebf8f52e790907d20f70a" // 加密key,根據需要自己生成 參考地址 https://crypot.51strive.com/sha256.html

  }

 

 

相關文章