Core3.0中Swagger使用JWT


前言

學習ASP.NETCore,原鏈接

https://www.cnblogs.com/laozhang-is-phi/p/9511869.html

原教程是Core2.2,后期也升級到了Core3.0,但是文章中和GitHub的代碼感覺有些亂,一直對應不上,

我創建的項目是Core3.0,而在Swagger中使用JWT一直訪問401,此處做個筆記,供以后學習時查看。

參考博文,原鏈接

https://www.cnblogs.com/CreateMyself/p/11123023.html

步驟

默認映射方式給移除掉

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

 

Swagger響應頭

這里需要Nuget引用Swashbuckle.AspNetCore.Filters,oauth2需要寫死,SecurityRequirementsOperationFilter中默認securitySchemaName="oauth2";

未添加該配置時,Bearer一直無法加入到JWT發起的Http請求的頭部,無論怎么請求都會是401;

用Postman在Authorization添加了Bearer,就會正常響應,

                #region Token綁定到ConfigureServices
                // 在header中添加token,傳遞到后台
                c.OperationFilter<SecurityRequirementsOperationFilter>();

                c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                {
                    Description = "JWT授權(數據將在請求頭中進行傳輸) 直接在下框中輸入Bearer {token}(注意兩者之間是一個空格)\"",
                    Name = "Authorization",//jwt默認的參數名稱
                    In = ParameterLocation.Header,//jwt默認存放Authorization信息的位置(請求頭中)
                    Type = SecuritySchemeType.ApiKey
                });
                #endregion

 

 啟用權限授權認證服務

            //JWT服務配置
            //讀取配置文件
            var audienceConfig = Configuration.GetSection("Audience");
            var symmetricKeyAsBase64 = audienceConfig["Secret"];

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                .AddJwtBearer(o =>
                {
                    o.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(symmetricKeyAsBase64)),//參數配置在下邊

                        ValidateIssuer = true,
                        ValidIssuer = audienceConfig["Issuer"],//發行人

                        ValidateAudience = true,
                        ValidAudience = audienceConfig["Audience"],//訂閱人

                        ValidateLifetime = true,

                        //ClockSkew = TimeSpan.Zero,//這個是緩沖過期時間,也就是說,即使我們配置了過期時間,這里也要考慮進去,過期時間+緩沖,默認好像是7分鍾,你可以直接設置為0
                        ClockSkew = TimeSpan.Zero,

                        RequireExpirationTime = true,
                    };
                });

 

Configure配置

這里的順序,必須嚴格遵守

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            //啟用認證中間件,
            app.UseAuthentication();
            //啟用授權中間件,
            app.UseAuthorization();

            #region swagger
            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });
            #endregion

            app.UseEndpoints(endpoints =>
            {
                //endpoints.MapControllers();

                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

 

 授權方法

這里的區別,jwt對象,多加了audience和expires屬性。

audience:就是配置的值,

expires:JWT過期時間,經過測試,JWT過期時間=expires + ClockSkew。並不是claims中的JwtRegisteredClaimNames.Exp去控制的過期時間

        public static string IssueJWT(TokenModel tokenModel, TimeSpan expiresSliding, TimeSpan expiresAbsoulte)
        {
            var Issuer = "Blog.Core";
            var Audience = "wr";
            var Secret = "sdfsdfsrty45634kkhllghtdgdfss345t678fs";

            var dateTime = DateTime.UtcNow;

            var claims = new Claim[]
                {
                    //下邊為Claim的默認配置
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
                //這個就是過期時間,目前是過期100秒,可自定義,注意JWT有自己的緩沖過期時間
                new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(180)).ToUnixTimeSeconds()}"),
                new Claim(JwtRegisteredClaimNames.Iss,Issuer),
                new Claim(JwtRegisteredClaimNames.Aud,Audience),
                //這個Role是官方UseAuthentication要要驗證的Role,我們就不用手動設置Role這個屬性了
                new Claim(ClaimTypes.Role,tokenModel.Role),
                new Claim(ClaimTypes.Name, tokenModel.Uname),
                new Claim(JwtRegisteredClaimNames.Email, tokenModel.EMail),
                new Claim(JwtRegisteredClaimNames.Sub,tokenModel.Sub),
               };

            //秘鑰
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Secret));

            var jwt = new JwtSecurityToken(
                issuer: Issuer,
                audience: Audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(1),
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
                );
            var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

            return encodedJwt;
        }

 

 appsetting.json

  "Audience": {
    "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
    "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。內容就是Secret
    "Issuer": "Blog.Core",
    "Audience": "wr"
  }

 

 Postman測試

Authorization => Bearer Token => Token,這里輸入登錄時生成的Token值,不需要帶Bearer 前綴

Postman 示例

 

 

 Swagger示例

 

 

 

 

 Fiddler監視

 

 

Roles配置權限

用戶的Role,與訪問接口配置的Roles不一致,也就是沒有訪問權限,訪問時會響應為403

總結

調用接口一直401

JWT配置需要驗證的東西,

 

 一直401,可能是JWT中未包含上面配置的全部參數

相比較之前,又傳遞了audience和expires參數,這樣訪問接口驗證必傳參數才能通過。

 授權

三種方式

(1)基於角色

(2)基於Claim聲明

(3)基於自定義的類

目前,前2個都測試通過的,第三個需要配合創建其他的東西,未實現。

 

            services.AddAuthorization(options =>
            {
                //1.基於角色
                options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
                options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
                //Client或者Admin
                options.AddPolicy("ClientOrAdmin", policy => policy.RequireRole("Client", "Admin").Build());
                //Client並且Admin
                options.AddPolicy("ClientAndAdmin", policy => policy.RequireRole("Client").RequireRole("Admin").Build());

                //2.基於聲明
                options.AddPolicy("AdminClaim2", policy => policy.RequireClaim(ClaimTypes.Name, "Yasuo", "Leesnn").Build());

                //3.基於需要Requirement
                //options.AddPolicy("AdminRequirement", policy => policy.Requirements.Add(new AdminRequirement() { UName = "Kate" }));
            });

 

        /// <summary>
        /// 獲取數據,需要授權
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [Authorize(Policy = "AdminClaim2")]
        [HttpPost("{name}")]
        public string PostUser(string name)
        {
            var sub = User.FindFirst(d => d.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name")?.Value;

            name += "---" + sub ?? "";

            return name + DateTime.Now.ToLongTimeString();
        }

 

 

 

 

 


免責聲明!

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



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