IdentityServer4 4.x版本 配置Scope的正確姿勢

来源:https://www.cnblogs.com/xhznl/archive/2020/07/03/13223964.html
-Advertisement-
Play Games

前言 IdentityServer4 是為ASP.NET Core系列量身打造的一款基於 OpenID Connect 和 OAuth 2.0 認證的框架 IdentityServer4官方文檔:https://identityserver4.readthedocs.io/ 看這篇文章前預設你對Id ...


前言

IdentityServer4 是為ASP.NET Core系列量身打造的一款基於 OpenID Connect 和 OAuth 2.0 認證的框架

IdentityServer4官方文檔:https://identityserver4.readthedocs.io/

看這篇文章前預設你對IdentityServer4 已經有一些瞭解。

本篇使用IdentityServer4的4.x版本,跟老版本的稍微有些差別。下麵直接進入正題。

鑒權中心

創建IdentityServer4項目

使用IdentityServer4 來搭建一個鑒權中心,首先建議安裝一下IdentityServer4的官方項目模板。也可以不安裝,自己創建項目,然後NuGet安裝需要的包也行。(不過還是推薦用官方的模板,很方便)。

命令行執行:dotnet new -i IdentityServer4.Templates

image-20200629205619088

安裝完成後會多出以下項目模板:

image-20200629205731577

我這裡選用is4inmem這個模板來創建項目,這個模板的數據都是寫死在記憶體中的,並且包含了Quickstart頁面,比較簡單方便。

來到我的項目目錄下執行:dotnet new is4inmem --name Idp

image-20200701190325246

執行完成會生成以下文件:

image-20200701195853822

VS2019打開項目:

image-20200701195955107

運行項目:

image-20200701200225015

配置ApiResource、ApiScope、Clients

修改Startup:

// in-memory, code config
builder.AddInMemoryIdentityResources(Config.IdentityResources);
builder.AddInMemoryApiScopes(Config.ApiScopes);
//添加API資源
builder.AddInMemoryApiResources(Config.ApiResources);
builder.AddInMemoryClients(Config.Clients);

這裡比之前版本多了一個添加ApiScopes的方法:

builder.AddInMemoryApiScopes(Config.ApiScopes);

因為我接下來有要保護的API資源,所以需要添加一行:

builder.AddInMemoryApiResources(Config.ApiResources);

Config中的代碼:

public static class Config
{
    public static IEnumerable<IdentityResource> IdentityResources =>
        new IdentityResource[]
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
        };

    public static IEnumerable<ApiScope> ApiScopes =>
        new ApiScope[]
        {
            new ApiScope("scope1"),
            //new ApiScope("scope2"),
        };

    public static IEnumerable<ApiResource> ApiResources =>
        new ApiResource[]
        {
            new ApiResource("api1","#api1")
            {
                //!!!重要
                Scopes = { "scope1"}
            },
            //new ApiResource("api2","#api2")
            //{
            //    //!!!重要
            //    Scopes = { "scope2"}
            //},
        };

    public static IEnumerable<Client> Clients =>
        new Client[]
        {
            new Client
            {
                ClientId = "postman client",
                ClientName = "Client Credentials Client",

                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets = { new Secret("postman secret".Sha256()) },

                AllowedScopes = { "scope1" }
            },
        };
}

我添加了一個ID為postman client的客戶端,授權模式就用最簡單的ClientCredentials客戶端模式。需要註意的是4.x版本的ApiScope和ApiResource是分開配置的,然後在ApiResource中一定要添加Scopes。如果你在網上搜的IdentityServer4教程比較老的,都是沒有這個ApiScope的,預設ApiResource的Name作為Scope。類似這樣:

public static IEnumerable<ApiResource> ApiResources =>
        new ApiResource[]
        {
            new ApiResource("api1","#api1"),//錯誤
            new ApiResource("api2","#api2"),//錯誤
        };


public static IEnumerable<Client> Clients =>
        new Client[]
        {
            new Client
            {
                ......

                AllowedScopes = { "api1", "api2" }
            },
        };

如果你這麼寫的話,雖然不影響你獲取token,但是你訪問api資源的話,永遠會得到一個401錯誤!!!
Audience validation failed. Audiences: 'xxx, http://xxx/resources'. Did not match: validationParameters.ValidAudience: 'xxx' or validationParameters.ValidAudiences: 'null'.

ApiResource

下麵添加一個api1資源,新建asp.netcore web應用並使用webapi模板:

image-20200701211036365

NuGet安裝:Microsoft.AspNetCore.Authentication.JwtBearer

Startup部分代碼:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            //IdentityServer地址
            options.Authority = "http://localhost:5001";
            //對應Idp中ApiResource的Name
            options.Audience = "api1";
            //不使用https
 		    options.RequireHttpsMetadata = false;
        });
}

// 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.UseHttpsRedirection();

    app.UseRouting();

    //身份驗證
    app.UseAuthentication();

    //授權
    app.UseAuthorization();

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

給WeatherForecastController添加[Authorize]標記:

image-20200701214601854

運行Api1Resource,用postman測試訪問weatherforecast介面:

image-20200701214742071

此時得到401錯誤。下麵先去Idp獲取一個token:

image-20200701215031535

拿到token後再去訪問weatherforecast就沒問題了:

image-20200701215748634

進行到這裡,好像跟scope都沒什麼關係,那麼scope到底有什麼用處呢?

ApiScope策略授權

繼續修改代碼。

Api1Resource項目NuGet安裝:IdentityServer4.AccessTokenValidation

image-20200701221017612

再新建一個TestController用於區分:

image-20200701223359517

下麵我需要做的是使用scope結合策略授權來分別限制TestController和WeatherForecastController的訪問許可權。

修改Startup:

public void ConfigureServices(IServiceCollection services)
{
    ......

    services.AddAuthorization(options =>
    {
        //基於策略授權
        options.AddPolicy("WeatherPolicy", builder =>
        {
            //客戶端Scope中包含api1.weather.scope才能訪問
            builder.RequireScope("api1.weather.scope");
        });
        //基於策略授權
        options.AddPolicy("TestPolicy", builder =>
        {
            //客戶端Scope中包含api1.test.scope才能訪問
            builder.RequireScope("api1.test.scope");
        });
    });
}

為了好理解,我把scope名稱分別改成了:api1.weather.scope和api1.test.scope。

WeatherForecastController的Authorize標記修改一下:[Authorize(Policy = "WeatherPolicy")]

TestController的代碼很簡單:

image-20200701224046637

因為修改了scope名稱,需要把Idp中的scope名稱也改一下:

public static IEnumerable<ApiScope> ApiScopes =>
    new ApiScope[]
    {
        new ApiScope("api1.weather.scope"),
        new ApiScope("api1.test.scope"),
        //new ApiScope("scope2"),
    };

public static IEnumerable<ApiResource> ApiResources =>
    new ApiResource[]
    {
        new ApiResource("api1","#api1")
        {
            //!!!重要
            Scopes = { "api1.weather.scope", "api1.test.scope" }
        },
        //new ApiResource("api2","#api2")
        //{
        //    //!!!重要
        //    Scopes = { "scope2"}
        //},
    };

客戶端定義,AllowedScopes暫時只給一個api1.weather.scope測試一下

public static IEnumerable<Client> Clients =>
            new Client[]
            {
                new Client
                {
                    ClientId = "postman client",
                    ClientName = "Client Credentials Client",

                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets = { new Secret("postman secret".Sha256()) },

                    AllowedScopes = { "api1.weather.scope" }
                },
            };

postman獲取token:

image-20200701225242813

訪問weatherforecast介面,正常響應200。

image-20200701225430395

再訪問test,得到403錯誤:

image-20200701225508071

接下來修改一下Idp的客戶端定義,添加api1.test.scope:

AllowedScopes = { "api1.weather.scope", "api1.test.scope" }

修改Idp後一定要重新獲取token,jwt就是這樣,一旦生成就無法改變。

image-20200701230022811

拿到新的token後訪問test和weatherforecast,這時候就都可以正常響應了。

image-20200701230107290

image-20200701230209695

總結

以上使用IdentityServer4搭建了一個鑒權中心,保護API資源,並使用ApiScope配合策略授權完成了一個簡單的許可權控制。IdentityServer4的玩法非常多,知識點也很多。強烈推薦B站的@solenovex 楊老師的視頻,地址:https://www.bilibili.com/video/BV16b411k7yM 多看幾遍,會有收穫。。。

需要代碼的點這裡:https://github.com/xiajingren/IdentityServer4-4.x-Scope-Demo


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

-Advertisement-
Play Games
更多相關文章
  • opencv——threshold閾值處理、自適應閾值處理、otsu處理(大津法) ...
  • 開胃菜 ——實現遍歷集合,開啟Stream流的便利化 import java.util.ArrayList; import java.util.Collections; public class Main{ public static void main(String[] args) { Array ...
  • hashCode介紹: hashCode()的作用是獲取哈希碼,它實際上是返回一個int整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode()定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode()函數。散列表存儲的是鍵值對(key-va ...
  • 今天介跟大家分享一下我平時閱讀源碼的幾個小技巧,對於閱讀java中間件如Spring、Dubbo等框架源碼的同學有一定幫助。 本文基於Eclipse IDE,我們每天都使用的IDE其實提供了很多強大的功能,掌握它們,往往能夠事半功倍。 1、Quick Type Hierarchy 快速查看類繼承體系 ...
  • 昵稱:(OrangeCsong)橘松(在其他平臺也是這個名字) 年齡:95後(摩羯座) 性別:boy 性格:性格還闊以,不輕易發脾氣,沉穩。喜歡獨立思考。 愛好:運動(工作了,運動時間太少),基金理財,很少玩游戲。 工作:杭漂程式🐶(後端開發) 坐標:杭州(江西銀,老表你來了) 公眾號:橘松Jav ...
  • C#中foreach的實現原理 在探討foreach如何內部如何實現這個問題之前,我們需要理解兩個C#裡邊的介面,IEnumerable 與 IEnumerator. 在C#裡邊的遍歷集合時用到的相關類中,IEnumerable是最基本的介面。這是一個可以進行泛型化的介面,比如說IEnumerabl ...
  • 使用博客園寫博客也有2年有餘了,對博客園是有一種莫名的親切感和深刻的感情的,這2多年來一直堅持寫著博客,也是對自己的一個很好的技術歷程總結。每次學習了一些新的技術,或者有一些感興趣的方向,都會通過隨筆進行記錄,有時候也會總結很多自己的開發成果,隨著技術路線的成熟,基本上是分享我的.NET相關技術。 ...
  • vs2019創建webapi 1.創建新的項目 2.選擇.NET CORE的ASP .NET CORE WEB應用程式 3.定義項目名稱和存放地點 4.選擇API創建項目 5.刪除原本的無用的類 6.添加新的方法類 7.設置路由 using Microsoft.AspNetCore.Componen ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...