IdentityServer4-MVC+Hybrid實現Claims授權驗證(四)

来源:https://www.cnblogs.com/FireworksEasyCool/archive/2018/12/26/10181525.html
-Advertisement-
Play Games

上節以對話形式,大概說了幾種客戶端授權模式的原理,這節重點介紹Hybrid模式在MVC下的使用。且為實現IdentityServer4從資料庫獲取User進行驗證,並對Claim進行許可權設置打下基礎(第五節介紹)。 本節內容比較多,且涉及一、二節的內容,如有不懂,可先熟悉一、二節知識。 一、新建授權 ...


上節以對話形式,大概說了幾種客戶端授權模式的原理,這節重點介紹Hybrid模式在MVC下的使用。且為實現IdentityServer4從資料庫獲取User進行驗證,並對Claim進行許可權設置打下基礎(第五節介紹)。

本節內容比較多,且涉及一、二節的內容,如有不懂,可先熟悉一、二節知識。


一、新建授權服務,命名為AuthServer

(1)新建Web API項目,不用配置HTTPS,不進行身份驗證。

設置成控制台方式運行,埠設為5000。

安裝IdentityServer4

在Config.cs類中,添加如下代碼:

public class Config
    {

        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>
            {
                new TestUser
                {
                    SubjectId = "1",
                    Username = "test",
                    Password = "123",

                    Claims = new List<Claim>
                    {
                        new Claim("role", "user")
                    }
                },
                new TestUser
                {
                    SubjectId = "2",
                    Username = "admin",
                    Password = "123",

                    Claims = new List<Claim>
                    {
                        new Claim("role", "admin")
                    }
                }
            };
        }

        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                //new IdentityResource("roles","role",new List<string>{ "role"})
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("api1", "My API")
                //new ApiResource("api1", "My API",new List<string>(){ "role"})
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    ClientId = "AuthServer",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" },
                    Claims= new List<Claim>(){new Claim("role","AuthServer") },
                    ClientClaimsPrefix = ""
                },
                // OpenID Connect implicit flow client (MVC)
                new Client
                {
                   ClientId = "mvc",
                   ClientName = "MVC Client",
                   AllowedGrantTypes = GrantTypes.Hybrid,
                   ClientSecrets =
                   {
                       new Secret("secret".Sha256())
                   },
                   // where to redirect to after login
                   RedirectUris = { "http://localhost:5002/signin-oidc" },

                   // where to redirect to after logout
                   PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

                  AllowedScopes = new List<string>
                  {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    //"roles"
                  }
                }
            };
        }
}

這裡IdentityResource映射於那些關於用戶信息的scope, ApiResource映射於API資源的scopes。

 

(2)打開Startup.cs,在ConfigureServices裡面調用AddIdentityServer來把Identity Server註冊到ASP.NET Core的容器裡面;隨後我調用了AddDeveloperSigningCredentials方法,它會創建一個用於對token簽名的臨時密鑰材料(但是在生產環境中應該使用可持久的密鑰材料)

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

            services.AddIdentityServer()
               .AddDeveloperSigningCredential()
               .AddTestUsers(Config.GetUsers())
               .AddInMemoryIdentityResources(Config.GetIdentityResources())
               .AddInMemoryApiResources(Config.GetApiResources())
               .AddInMemoryClients(Config.GetClients());
        }

(3)打開Configure方法,把IdentityServer添加到ASP.NET Core的管道里。

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

            app.UseIdentityServer();
            //MVC配置
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }

(4)然後下載登錄用的UI: https://github.com/IdentityServer/IdentityServer4.Quickstart.UI

把圖中三個文件複製到AuthServer項目目錄下。

複製完後項目如下:


 

二、新建MVC客戶端,命名為MvcClient

(1)設置埠為5002。

修改Start.cs的ConfigureServices方法為:

public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc();

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies", options => 
            {
                //無許可權,顯示的頁面
                options.AccessDeniedPath = "/Authorization/AccessDenied";
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";

                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ClientId = "mvc";
                options.ResponseType = "code id_token";
                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                //options.Scope.Add("roles");

                options.SaveTokens = true;
                options.ClientSecret = "secret";
                options.GetClaimsFromUserInfoEndpoint = true;

                //options.ClaimActions.MapUniqueJsonKey("role", "role");


                //options.TokenValidationParameters = new TokenValidationParameters
                //{
                //    NameClaimType = JwtClaimTypes.GivenName,
                //    RoleClaimType = JwtClaimTypes.Role
                //};
            });
       }

AddAuthentication方法來添加和配置身份認證中間件。這裡使用Cookie作為驗證用戶的首選方式,而DefaultScheme = "Cookies",這個"Cookies"字元串是可以任意填寫的,只要與後邊的一致即可。但是如果同一個伺服器上有很多應用的話,這個Scheme的名字不能重覆。

DefaultChanllangeScheme設為"oidc", 這個名字與後邊配置OpenIdConnect的名字要一樣. 當用戶需要登陸的時候, 將使用的是OpenId Connect Scheme。

AddCookie其參數是之前配置的DefaultScheme名稱,這配置了Cookie的處理者,並讓應用程式為我們的DefaultScheme啟用了基於Cookie的身份認證。一旦ID Token驗證成功並且轉化為Claims身份標識後,這些信息就將會保存於被加密的Cookie里。

AddOpenIdConnect方法添加了對OpenID Connect流程的支持,它讓配置了用來執行OpenId Connect 協議的處理者。這個處理者會負責創建身份認證請求,Token請求和其它請求,並負責ID Token的驗證工作。它的身份認證scheme就是之前配置的"oidc",它的意思就是如果該客戶端的某部分要求身份認證的時候,OpenID Connect將會作為預設方案被觸發(因為之前設置的DefaultChallengeScheme是"oidc", 和這裡的名字一樣)。

SignInScheme和上面的DefaultScheme一致,它保證身份認證成功的結果將會被保存在方案名為"Cookies"的Cookie里。

Authority就是Identity Provider的地址。

ClientIdSecret要與IdentityProvider裡面的值一樣。

請求的Scope有openid和profile,其實中間件預設也包括了這些scope,但是寫出來更明確一些。

SaveTokens=true,表示允許存儲從Identity Provider那裡獲得的tokens。

 

(2)修改Configure方法為:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseAuthentication();

            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }

(3)然後對HomeController加上身份驗證。[Authorize]

(4)再修改About的頁面,顯示User的Claim信息。

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>

@*<dt>Access Token</dt>
<dd>@ViewData["AccessToken"]</dd>*@

<dl>
    @foreach (var claim in User.Claims)
    {
        <dt>@claim.Type</dt>
        <dd>@claim.Value</dd>
    }
</dl>

 

(5)現在,可以運行AuthServer和MvcClient項目了。

(6)輸入Config文件中的TestUser的用戶,密碼都設為123,點擊Login

允許授權

查看About頁面,顯示了user相關的claim信息。

(7)當然,登出功能還沒實現,這裡先實現登出。打開圖中cshtml文件

添加如下代碼:

 @if (User.Identity.IsAuthenticated)
 {
     <li><a asp-area="" asp-controller="Home" asp-action="Logout">Logout</a></li>
 }

然後在HomeController控制器中添加Logout方法

  public async Task Logout()

        {

            await HttpContext.SignOutAsync("Cookies");

            await HttpContext.SignOutAsync("oidc");

        }

首先要清除本地的Cookie,這個Cookie的名字要與之前配置的預設方案里的名字一致,這一步就相當於登出MVC客戶端。

後一行代碼的作用是跳轉回到Identity Provider,然後用戶可以繼續登出IDP, 也就是IDP會清除它的Cookie。

(8)接著在AuthServer中的Quickstart/Account/AccountOptions實現自動跳轉回登錄頁面。

好了,登錄登出實現完了,我們接著實現Claim許可權限制。


 

三、為MVC客戶端設置Claim身份驗證

(1)添加TestUser的Claim中Type為role

(2)定義用戶信息scope的role信息

第一個參數是scope的名字,第二個參數是scope的顯示名,第三個參數是它所包含的claim類型,這裡就是“role”。

(3)然後還需要客戶端允許請求“roles”這個scope

 

(4)MVC客戶端的配置,打開MVC的startup,添加“roles”這個scope:options.Scope.Add("roles");

 把role claim 映射到User.Claims里:options.ClaimActions.MapUniqueJsonKey("role", "role");

 role claim映射成ASP.NET Core MVC可以識別的角色Roles。

options.TokenValidationParameters = new TokenValidationParameters
{
    NameClaimType = JwtClaimTypes.GivenName,
    RoleClaimType = JwtClaimTypes.Role
};

這樣MVC中的role就可以識別User.Claims的role了。

(6)最後在MvcClient項目HomeController中   About前,加上role為admin身份驗證。[Authorize(Roles ="admin")]

然後運行,先用test賬號登錄進行驗證。

發現點About頁面沒有許可權進不去

然後登出,換admin賬號登錄

User.Claims的role成功被MVC中角色role識別,展示About頁面。


 

這節主要介紹Hybrid在MVC下的使用,包括User的登錄登出和Claim對MVC的身份授權。

然而,這隻是針對記憶體用戶TestUser進行操作的,顯示實際項目中不能滿足我們需求。下節將在本節的基礎上介紹如何實現IdentityServer4從資料庫獲取User進行驗證並對Claim進行身份驗證。

參考博客: https://www.cnblogs.com/cgzl/p/9268371.html

源碼地址:https://github.com/Bingjian-Zhu/Mvc-HybridFlowV0.git


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

-Advertisement-
Play Games
更多相關文章
  • C# 學習總結 C#-簡介(一) C#-hello world(二) C#-基本語法(三) C#-運算符(四) C#-判斷語句(五) C#-迴圈語句(六) C#-封裝(七) C#-方法(八) C#-類(九) C#-結構體(十) C#-繼承(十一) C#-多態(十二) C#-枚舉(十三) C#-異常處 ...
  • 在代碼中正確配置了log4net後,IIS上仍然不能寫日誌的情況下,只需在寫日誌的目錄添加 IIS_IUSRS 用戶,並賦與讀寫許可權即可。 ...
  • 來自:http://www.cnblogs.com/emanlee/p/3587571.html ...
  • 相信很多學習和開發wpf項目的同學都瞭解過mvvm模式,同樣,在mvvm模式下會有一個不可忽視的問題,就是怎麼在xaml中彈出窗體,而不破壞MVVM本身的結構。 關於彈出窗體的方式還是很多的,本文先講一下用觸發器做處理。 我們先要在xaml中引用 xmlns:i="http://schemas.mi ...
  • 生成解決方案時報“error CS0006: Metadata file '.../.../.../xxx.dll'could not be found"。 錯誤列表-下拉框選擇整個解決方案-錯誤,發現代碼裡面有兩個錯誤,改完錯誤再生成就好了。 ...
  • 取消令牌(CancellationToken) 是 .Net Core 中的一項重要功能,正確併合理的使用 CancellationToken 可以讓業務達到簡化代碼、提升服務性能的效果;當在業務開發中,需要對一些特定的應用場景進行深度干預的時候,CancellationToken 將發揮非常重要的... ...
  • “安裝”階段發生異常。System.ComponentModel.Win32Exception:遠程過程調用失敗 附上提示信息C:\Windows\Microsoft.NET\Framework\v4.0.30319>installUtil.exe C:\Users\Administrator\De ...
  • 本節將在第四節基礎上介紹如何實現IdentityServer4從資料庫獲取User進行驗證,並對Claim進行許可權設置。 一、新建Web API資源服務,命名為ResourceAPI (1)新建API項目,用來進行user的身份驗證服務。 (2)配置埠為5001 安裝Microsoft.Entit ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...