.Net Core Jwt鑒權授權

来源:https://www.cnblogs.com/qfccc/archive/2023/07/09/17539518.html
-Advertisement-
Play Games

[toc] # 簡介 - Jwt分為三段 通過遠點分割 1. header => 描述這個token加密方式 2. PlayLoad => 有效載荷,用戶信息+自定義Claims信息Verify 3. Signature => 簽名, (頭部信息base64處理,有效載荷base64處理) + 密鑰 ...


目錄

簡介

  • Jwt分為三段 通過遠點分割
  1. header => 描述這個token加密方式
  2. PlayLoad => 有效載荷,用戶信息+自定義Claims信息Verify
  3. Signature => 簽名, (頭部信息base64處理,有效載荷base64處理) + 密鑰
  • 示例 :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJFeHRlbmRlZDEiOiLml6Dkv6Hmga8iLCJFeHRlbmRlZDIiOiIiLCJFeHRlbmRlZDMiOiIiLCJFeHRlbmRlZDQiOiIiLCJFeHRlbmRlZDUiOiIiLCIxIjoi57O757uf566h55CG5ZGYIiwiMiI6IueUqOaIt-euoeeQhuWRmCIsImV4cCI6MTY4ODkwMTA2NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDg4IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo1MDg4In0.7J1J7yWj4ELHJZIwLKnT4RgcMu3rGAX5ACBFfCS0LWM

基於.Net Core 驗證方式

  1. 生成jwtToken
  2. 標記[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
  3. 驗證 Issuer
  4. 驗證 Audience
  5. 驗證 SecurityKey
  6. 驗證自定義驗證
  7. 驗證完成可以正常訪問介面

驗證的那幾步順序可以直接在自定義驗證中驗證

Jwt獲取Token

引入三方包

<ItemGroup>
    <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.31.0" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
</ItemGroup>

生成Token


using Microsoft.IdentityModel.Tokens;
using Programming.DotNetCore.Function.Entity.Jwt;
using Programming.DotNetCore.Function.Interface.PasswordService;
using Programming.DotNetCore.Function.Password.Entity;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Programming.DotNetCore.Function.Password
{
    public class JwtServices : IPassWordService
    {
        public string GetToken(UserInfo user,JwtConfig jwtConfig)
        {
            List<Claim> claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.UserName ?? ""),
                new Claim("Extended1", user.Extended1 ?? ""),
                new Claim("Extended2", user.Extended2 ?? ""),
                new Claim("Extended3", user.Extended3 ?? ""),
                new Claim("Extended4", user.Extended4 ?? ""),
                new Claim("Extended5", user.Extended5 ?? ""),
            };
            if (user.Role is not null)
            {
                foreach (var item in user.Role)
                {
                    claims.Add(new Claim(item.Id.ToString(), item.Role));
                }
            }
            if(jwtConfig.SecurityKey == null)
            {
                throw new Exception("JwtConfig.SecurityKey 不能為空");
            }
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey));
            SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            JwtSecurityToken token = new JwtSecurityToken(
                issuer:jwtConfig.Issuer,
                audience:jwtConfig.Audience,
                claims:claims,
                expires: DateTime.UtcNow.AddMinutes(jwtConfig.ExpiresMinutes),
                signingCredentials:creds
            );
            string resultToken = new JwtSecurityTokenHandler().WriteToken(token);
            return resultToken;
        }
    }
}

UserInfo

namespace Programming.DotNetCore.Function.Password.Entity
{
    public class UserInfo
    {
        public string? UserName { get; set; }
        public List<RoleInfo>? Role { get; set; }
        public string? Extended1 { get; set; }
        public string? Extended2 { get; set; }
        public string? Extended3 { get; set; }
        public string? Extended4 { get; set; }
        public string? Extended5 { get; set; }
    }
}

JwtConfig

namespace Programming.DotNetCore.Function.Entity.Jwt
{
    public class JwtConfig
    {
        public string? Audience { get; set; }
        public string? Issuer { get; set; }
        public string? SecurityKey { get; set; }
        public int ExpiresMinutes { get; set; }
    }
}

WebApi測試(獲取Token)

Program.cs

//讀取Jwt配置
builder.Services.Configure<JwtConfig>(builder.Configuration.GetSection("JwtTokenOptions"));

appsetting.json

{
  "JwtTokenOptions": {
    "Issuer": "http://localhost:5088",
    "Audience": "http://localhost:5088",
    "SecurityKey": "kq4DY5N1eFJhscOkI7Zp4Nd0WNy9d9AEsN6Yjgdv9OxLyol66tzGBKT_7vwolN7GZ8EDwqJBwccjDJfb81ws5s3sbbP5wUzQ3-PcTSsD-Rueiu2rsOUZwg_NR3RBCwmtouV-832YV2trCjNTawLB1z0LMukWGFNaAJVZ8WdQcrYn6a0ko5oVhZqaHBgsCLEGiqPtoFsiCcrJTz1IvXHk9_cDSr2hwEmSl18GlkOtgCHFH8aidYth3aQHRHuClTi6Y9mYRJtqqK-FNQYq4ZP23DSGZGFejJFTnM9YMpppuTMLklhSGySwX8rfjZ_0L5ac18nHaykTaiC2fvH00W42qQ"
  }
}

Controller

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Programming.DotNetCore.Function.Entity.Jwt;
using Programming.DotNetCore.Function.Interface.PasswordService;
using Programming.DotNetCore.Function.Password.Entity;

namespace Cnpc.Com.Ioc.WebApp.Controllers
{
    [Route("api/[controller]/[Action]")]
    [ApiController]
    public class TestJwtController : ControllerBase
    {
        IPassWordService _passWordService;
        JwtConfig _jwtconfig;

        public TestJwtController(IPassWordService passWordService,IOptions<JwtConfig> jwtconfig) 
        {
            _passWordService = passWordService;
            _jwtconfig = jwtconfig.Value;
        }

        [HttpGet]
        public IActionResult Login(string userName,string passWord)
        {
            string token = _passWordService.GetToken(new()
            {
                UserName = userName,
                Extended1 = "無信息",
                Role = new List<RoleInfo>() 
                { 
                    new RoleInfo() { Id = "1",Role="系統管理員"} ,
                    new RoleInfo() { Id = "2",Role="用戶管理員"} ,
                }
            }, new()
            {
                Audience = _jwtconfig.Audience,
                Issuer= _jwtconfig.Issuer,
                SecurityKey= _jwtconfig.SecurityKey,
                ExpiresMinutes = 5,
            });

            return new JsonResult(new { token = token }); 
        }
    }
}

.Net Core 驗證(webApi)

Progarm

添加JWT驗證

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidIssuer = jwtConfig.Issuer, //發行人
        ValidateAudience = true,
        ValidAudience = jwtConfig.Audience,//訂閱人
        ValidateIssuerSigningKey = true,
        //對稱加密密鑰
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey!)),
        ValidateLifetime = true, //驗證失效時間
        ClockSkew = TimeSpan.FromSeconds(30), //過期時間容錯值
        RequireExpirationTime = true,
        AudienceValidator = (audiences, securityToken, validationParameters) =>
        {
            return true;
        },
        LifetimeValidator = (notBefore,expires,  securityToken, validationParameters) =>
        {
            return true;
        }
    };
});

讀取配置文件

JwtConfig jwtConfig = new JwtConfig();
builder.Configuration.Bind("JwtTokenOptions", jwtConfig);

添加Swagger支持,api右上角可以寫Token

builder.Services.AddSwaggerGen(c =>
{
    //添加Jwt驗證設置,添加請求頭信息
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Id = "Bearer",
                    Type = ReferenceType.SecurityScheme
                }
            },
            new List<string>()
        }
    });

    //放置介面Auth授權按鈕
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "Value Bearer {token}",
        Name = "Authorization",//jwt預設的參數名稱
        In = ParameterLocation.Header,//jwt預設存放Authorization信息的位置(請求頭中)
        Type = SecuritySchemeType.ApiKey
    });
}); ;

Contorller

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Programming.DotNetCore.Function.Entity.Jwt;
using Programming.DotNetCore.Function.Interface.PasswordService;
using Programming.DotNetCore.Function.Password.Entity;

namespace Cnpc.Com.Ioc.WebApp.Controllers
{
    [Route("api/[controller]/[Action]")]
    [ApiController]
    public class TestJwtController : ControllerBase
    {
        [HttpGet]
        [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        public IActionResult TestApi()
        {
            //獲取用戶Claim信息
            var user = HttpContext.User.Claims.Select(it => new { it.Type,it.Value});
            return new JsonResult(user);
        }
    }
}

.Net Core 授權

簡介

可以在資料庫中進一步驗證訪問介面的許可權

Program.cs

//jwt 授權
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("JwtPolicy", policy =>
    {
        //jwt 授權
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        //這裡為自定義授權指定一下類
        .AddRequirements(new UserRoleRequirement(JwtBearerDefaults.AuthenticationScheme)); 
    });
});

JwtAuthorization.cs

註意

驗證中涉及到 IUserServices 和 JwtAuthorization, 需要在ioc容器中註冊一下,我這裡使用的是Autofac註冊,如果使用系統自帶的註冊可以這麼寫:

  • builder.Services.AddTransient<IUserServices, IUserServices>();
  • builder.Services.AddTransient<IAuthorizationHandler, JwtAuthorization>();

Autofac 註冊授權服務

using Autofac;
using Autofac.Extras.DynamicProxy;
using Castle.DynamicProxy;
using Cnpc.Com.Ioc.Bll;
using Cnpc.Com.Ioc.Dal;
using Cnpc.Com.Ioc.IBll;
using Cnpc.Com.Ioc.IDal;
using Cnpc.Com.Ioc.Tools;
using Cnpc.Com.Ioc.WebApp.Authorization;
using Cnpc.Com.Ioc.WebApp.Filter.ActionFilter;
using Microsoft.AspNetCore.Authorization;
using Programming.DotNetCore.Function.Interface.PasswordService;
using Programming.DotNetCore.Function.Password;

namespace WepApiTest.Autofac
{
    public class AutofacConfig : Module
    {

        protected override void Load(ContainerBuilder builder)
        {
            //ioc
            builder.RegisterType<JwtAuthorization>().As<IAuthorizationHandler>();
            builder.RegisterType<UserServices>().As<IUserServices>();
        }
    }
}
using Cnpc.Com.Ioc.IBll;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;

namespace Cnpc.Com.Ioc.WebApp.Authorization
{
    public class UserRoleRequirement : IAuthorizationRequirement
    {
        public string AuthenticateScheme;
        public UserRoleRequirement(string authenticateScheme)
        {
            AuthenticateScheme = authenticateScheme;
        }
    }
    public class JwtAuthorization : AuthorizationHandler<UserRoleRequirement>
    {
        IUserServices userSercices;
        public JwtAuthorization(IUserServices userSercices)
        {
            this.userSercices = userSercices;
        }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserRoleRequirement requirement)
        {
            string? userName = context.User.FindFirst(it => it.Type == ClaimTypes.Name)?.Value;
            if (userSercices.IsAdmin(userName!))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
            return Task.CompletedTask;
        }
    }
}

Controller

註意

唯一需要修改的地方就是這裡, 指定Policy 為 Program.cs 中設置授權方案名稱

  • [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme,Policy = "JwtPolicy")]
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Programming.DotNetCore.Function.Entity.Jwt;
using Programming.DotNetCore.Function.Interface.PasswordService;
using Programming.DotNetCore.Function.Password.Entity;

namespace Cnpc.Com.Ioc.WebApp.Controllers
{
    [Route("api/[controller]/[Action]")]
    [ApiController]
    public class TestJwtController : ControllerBase
    {
        [HttpGet]
        [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme,Policy = "JwtPolicy")]
        public IActionResult TestApi()
        {
            var user = HttpContext.User.Claims.Select(it => new { it.Type,it.Value});
            return new JsonResult(user);
        }
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • - 背景: 經常創建和銷毀,使用量特別大的資源,比如併發情況下的線程,對性能影響很大。 - 思路:提前創建好多個線程,放入線程池中,使用時直接獲取,使用完放後池中。可以避免頻繁創建銷毀,實現重覆利用。類似生活中公共交通工具。 - 好處: - 提高響應速度(減少了創建新線程的時間) - 降低資源消耗( ...
  • **本文深入探討了 Django 中的請求與響應處理,從 Django 請求和響應的基礎知識、生命周期,到 HttpRequest 和 HttpResponse 對象的詳細介紹。同時,討論了 Django 的視圖和請求、響應處理,以及安全性和非同步處理的考慮。最後,對比了 Django 與 Flask ...
  • ### 三種創建方式 - Thread class 繼承Thread類 - Runnable介面 實現Runnable介面 - Callable介面 實現Callable介面 ### Thread - 自定義線程類繼承Thread類 - 重寫run()方法,編寫線程執行體 - 創建線程對象,調用st ...
  • python打包Windows.exe程式(pyinstaller) ## 基礎命令 `pip install pyinstaller` 使用pip命令來安裝pyinstaller模塊。 -F: `pyinstaller -F hello.py -p hello2.py` -D: `pyinstal ...
  • 編寫測試可以讓我們的代碼在後續迭代過程中不出現功能性缺陷問題;理解迭代器、閉包的函數式編程特性;`Box ...
  • 本文主要介紹如何通過 docker-maven-plugin 插件把 Java 服務構建成 docker 鏡像;文中所使用到的軟體版本:Docker 20.10.17、Java 1.8.0_341、SpringBoot 2.7.12、Maven 3.8.4、docker-maven-plugin 1 ...
  • 如果我說可以用java對nginx進行擴展,就像OpenResty支持Lua擴展一樣,您相信嗎?一起來體驗nginx-clojure吧 ...
  • 緩存數據同步策略示意圖 在大多數情況下,我們通過瀏覽器查詢到的數據都是緩存數據,如果緩存數據與資料庫的數據存在較大差異的話,可能會產生比較嚴重的後果的。所以,我們應該也必須保證資料庫數據、緩存數據的一致性,這就是緩存與資料庫的同步。 緩存數據同步策略 緩存數據同步,常見的有三種方式: 1:設置有效期 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...