.NET Core的JWT認證的學習


今天學習下JWT,遇到了兩個坑爹問題,這里記錄下。在 ASP.NET Core 中,授權的設置方式有兩種,可以使用角色,也可以使用策略,這里也將簡單舉例角色、策略的使用。

JWT這里不做介紹,如果想了解更多,請看https://www.jianshu.com/p/a12fc67c9e05,https://www.cnblogs.com/CreateMyself/p/11123023.html ,這兩篇都講解的很好,這里只寫實際的使用和遇到的問題。

1. JWT的SecretKey必須16位以上

jwt中key必須16位以上,否則長度不夠會拋出異常,異常代碼如下

System.ArgumentOutOfRangeException
  HResult=0x80131502
  Message=IDX10603: Decryption failed. Keys tried: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
Exceptions caught:
 '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
token: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]' 
  Source=Microsoft.IdentityModel.Tokens
  StackTrace:
   at Microsoft.IdentityModel.Tokens.SymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
....................

2.獲取token之后,一直401Unauthorized

在Startup.cs中的Configure中添加app.UseAuthentication();新創建.net core項目的時候,會自動添加授權app.UseAuthorization();但是JWT其實是一種認證,准確;來說是登錄的過程,需要用戶名和密碼的認證。

例如:你要登陸論壇,輸入用戶名張三,密碼1234,密碼正確,證明你張三確實是張三,這就是 認證authentication;那么是否有刪除添加等的操作,這就是授權authorization

3.JWTtoken的獲取

//appsettings.json中增加配置信息
"JwtSettings": {
    "Issuer": "https://localhost:44378/",
    "Audience": "https://localhost:44378/",
    "SecretKey": "1234567890123456"
  }
View Code
// Startup.cs中增加JWT的設置           
            services.AddAuthentication(options =>
            {
                //認證middleware配置
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                //主要是jwt  token參數設置
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    //Token頒發機構
                    ValidIssuer = jwtSettings.Issuer,
                    //頒發給誰
                    ValidAudience = jwtSettings.Audience,
                    //這里的key要進行加密,需要引用Microsoft.IdentityModel.Tokens
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)),
                    ValidateIssuerSigningKey = true,
                    //是否驗證Token有效期,使用當前時間與Token的Claims中的NotBefore和Expires對比
                    ValidateLifetime = true,
                    //允許的服務器時間偏移量
                    ClockSkew = TimeSpan.Zero

                };
            });
View Code
// Controller中獲取token       
        [HttpPost]
        public IActionResult Token(LoginModel login)
        {
            _logger.LogInformation($"獲取Token:User:{login.User}");
            if (string.IsNullOrEmpty(login.User) || string.IsNullOrEmpty(login.Password))//判斷賬號密碼是否正確
            {
                return BadRequest();
            }


            var claim = new List<Claim>{
                    new Claim(ClaimTypes.Name,login.User),
                    new Claim(ClaimTypes.Role,"Test")
                };

            //建立增加策略的授權
            if (login.User == "Test") claim.Add(new Claim("Test", "Test"));
            if (login.User == "Test1") claim.Add(new Claim("Test", "Test1"));
            if (login.User == "Test2") claim.Add(new Claim("Test", "Test2"));
            if (login.User == "Test3") claim.Add(new Claim("Test", "Test3"));

            //對稱秘鑰
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));
            //簽名證書(秘鑰,加密算法)
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //生成token  [注意]需要nuget添加Microsoft.AspNetCore.Authentication.JwtBearer包,並引用System.IdentityModel.Tokens.Jwt命名空間
            var token = new JwtSecurityToken(_jwtSettings.Issuer, _jwtSettings.Audience, claim, DateTime.Now, DateTime.Now.AddMinutes(30), creds);

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

4.基於角色的授權

        [HttpGet]
        [Authorize(Roles ="Test")]
        public ActionResult<string> AuthValue()
        {
            var name = User.FindFirst(ClaimTypes.Name)?.Value;
            var role = User.FindFirst(ClaimTypes.Role)?.Value;
            _logger.LogInformation($"權限登錄,用戶名:{name},角色:{role}");

            return $"權限登錄,用戶名:{name},角色:{role}";
        }
Roles角色如果有多個,可以以逗號隔開。

5.基於策略的授權

//Startup.cs中添加策略
services.AddAuthorization(options => { options.AddPolicy("OnlyTestAccess", policy => policy.RequireClaim("Test", new string[] { "Test1", "Test2" })); options.AddPolicy("DepartmentAccess", policy => policy.RequireClaim("Department")); });
        // 方法上增加策略    
[HttpGet] [Authorize(Policy
= "OnlyTestAccess")] public ActionResult<string> AuthExtensionValue() { var name = User.FindFirst(ClaimTypes.Name)?.Value; var role = User.FindFirst(ClaimTypes.Role)?.Value; _logger.LogInformation($"基於策略的登錄,用戶名:{name},角色:{role}"); return $"基於策略的登錄,用戶名:{name},角色:{role}"; }

6.運行的截圖

 
        

7.Github上的源碼

https://github.com/jasonhua95/samll-project/tree/master/JwtApiDemo

 


免責聲明!

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



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