.NET CORE web api 集成jwt登錄認證


一、什么是JSON Web令牌?

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

  雖然JWT可以被加密以在各方之間提供保密性,但我們將重點關注簽名令牌。簽名令牌可以驗證其中包含的聲明的完整性,而加密令牌會對其他方隱藏這些聲明。當使用公鑰/私鑰對令牌進行簽名時,簽名還證明只有持有私鑰的一方才是簽名方。

二、When should you use JSON Web Tokens?

  以下是一些JSON Web標記有用的場景:

  授權:這是使用JWT最常見的場景。用戶登錄后,每個后續請求都將包括JWT,允許用戶訪問該令牌允許的路由、服務和資源。單點登錄是目前廣泛使用JWT的一種功能,因為它的開銷很小,並且能夠輕松地跨不同的域使用。

  信息交換:JSON Web令牌是在各方之間安全傳輸信息的好方法。因為JWT可以簽名,例如,使用公鑰/私鑰對,您可以確保發送者是他們所說的人。此外,由於簽名是使用報頭和有效載荷計算的,因此您還可以驗證內容沒有被篡改。

  什么是JSON Web令牌結構?

  在緊湊的形式中,JSON Web標記由三部分組成,由點(.)分隔,它們是:標題  有效載荷  簽名

  因此,JWT通常如下所示。

  xxxxx。YYYY。zzzzz

  讓我們把不同的部分分解一下。 

  標題

  標頭通常由兩部分組成:令牌的類型(JWT)和正在使用的簽名算法(如HMAC SHA256或RSA)。

  For example:

  {
  "alg": "HS256",
  "typ": "JWT"
  }
  Then, this JSON is Base64Url encoded to form the first part of the JWT.

  有效載荷

  令牌的第二部分是有效載荷,其中包含聲明。聲明是關於實體(通常是用戶)和其他數據的聲明。索賠有三種類型:登記索賠、公開索賠和私人索賠。

   注冊聲明:這些聲明是一組預定義的聲明,不是強制性的,而是推薦的,以提供一組有用的、可互操作的聲明。其中一些是:iss(發行人)、exp(到期時間)、sub(主題)、aud(觀眾)和其他。

  公開聲明:這些聲明可以由使用JWTs的人隨意定義。但為了避免沖突,它們應該在IANA JSON Web令牌注冊表中定義,或者定義為包含防沖突命名空間的URI。

      私人索賠:這些自定義索賠是為了在同意使用它們的各方之間共享信息而創建的,既不是注冊索賠,也不是公開索賠。

  

  An example payload could be:

  {
    "sub": "1234567890",    "name": "John Doe",    "admin": true   } 

  The payload is then Base64Url encoded to form the second part of the JSON Web Token.

  Signature

  To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

  For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:

  簽名

  要創建簽名部分,您必須獲取編碼的報頭、編碼的有效負載、一個秘密、報頭中指定的算法,並對其進行簽名。 

  例如,如果要使用HMAC SHA256算法,則將按以下方式創建簽名:

  HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

  簽名用於驗證消息在發送過程中沒有發生更改,如果是使用私鑰簽名的令牌,它還可以驗證JWT的發送者是它所說的人。

  綜合起來

  輸出是三個由點分隔的Base64 URL字符串,可以在HTML和HTTP環境中輕松傳遞,同時與基於XML的標准(如SAML)相比更加緊湊。 

  下面顯示了一個JWT,它對前一個頭和有效負載進行了編碼,並用一個秘密進行了簽名。

 

 

 

  如果您想使用JWT並將這些概念付諸實踐,可以使用JWT.io,用於解碼、驗證和生成JWT

三、JSON Web令牌是如何工作的?

  在身份驗證中,當用戶使用其憑據成功登錄時,將返回一個JSON Web令牌。由於令牌是憑證,因此必須非常小心地防止安全問題。一般來說,您不應該將代幣保存的時間超過所需時間。由於缺乏安全性,您也不應該在瀏覽器存儲中存儲敏感會話數據。 每當用戶想要訪問受保護的路由或資源時,用戶代理都應該發送JWT,通常在使用承載模式的授權報頭中。標題的內容應如下所示:

  

Authorization: Bearer <token>

  在某些情況下,這可能是一種無狀態授權機制。服務器的受保護路由將在授權頭中檢查有效的JWT,如果存在,則允許用戶訪問受保護的資源。如果JWT包含必要的數據,可能會減少查詢數據庫中某些操作的需要,盡管情況並非總是如此。請注意,如果通過HTTP頭發送JWT令牌,則應盡量防止它們變得太大。有些服務器不接受超過8KB的頭文件。如果您試圖在JWT令牌中嵌入太多信息,比如通過包含所有用戶的權限,那么您可能需要另一種解決方案,比如Auth0細粒度授權。如果令牌在授權頭中發送,則跨源資源共享(CORS)不會成為問題,因為它不使用cookie。

  下圖顯示了如何獲取JWT並使用其訪問API或資源:

   

 

     請注意,對於簽名令牌,令牌中包含的所有信息都會暴露給用戶或其他方,即使他們無法更改。這意味着您不應該將機密信息放入令牌中。

 

四、.NET CORE  添加jwt認證

1、新建jwt參數類

    public class TokenConfig
    {

        /// <summary>
        /// 密鑰
        /// </summary>
        public static string secret = "9999999999999999999999999";
        /// <summary>
        /// 簽發者
        /// </summary>
        public static  string issuer = "yinmingneng";
        /// <summary>
        /// 受眾
        /// </summary>
        public static  string audience = "ymn";
        /// <summary>
        /// 令牌過期時間
        /// </summary>
        public static  int accessExpiration = 20;
    }

二、身份認證設置成jwt認證,

uilder.Services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x => { 
    x.RequireHttpsMetadata= false;
    x.SaveToken = true;
    x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(TokenConfig.secret)),
        ValidIssuer = TokenConfig.issuer,
        ValidAudience = TokenConfig.audience,
        ValidateIssuer = false,
        ValidateAudience = false
    };
    x.Events = new JwtBearerEvents()
    {
        OnMessageReceived = context =>
        {
            context.Token = context.Request.Query["access_token"];
            return Task.CompletedTask;
        },
        OnAuthenticationFailed = context =>
        {
            // 如果過期,則把<是否過期>添加到,返回頭信息中
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return Task.CompletedTask;
        }
    };

});

三、新建一個控制器,用於模擬登錄,返回Token

 public class Authorization : Controller
    {

        [HttpGet("GetToken")]
        public string GetToken() {
            //載荷增加用戶
            var claims = new[] {
             new    Claim(ClaimTypes.Name,"yinmingneng"),
             new Claim(ClaimTypes.Email,"123@qq.com")
            };
            //加密密鑰
            var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(TokenConfig.secret));
            ///簽名
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwttoken = new JwtSecurityToken(TokenConfig.issuer,TokenConfig.audience, claims, DateTime.Now
                ,DateTime.Now.AddMinutes(TokenConfig.accessExpiration),credentials);
            var token =  new JwtSecurityTokenHandler().WriteToken(jwttoken);
            return token;
        }
        
    }

 

四、測試Token,新建一個控制器,控制器上增加[Authorize]權限認證,增加表示必須攜帶Token才能訪問

    [ApiController]
    [Route("[controller]")]
    [Authorize]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

五、測試、獲取Token訪問方法

 

 

 

使用Token,訪問,如果不攜帶會提示無權限訪問,比如

 

 

 

攜帶Token訪問,

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM