IdentityServer4實現OAuth2.0四種模式之客戶端模式


一,准備內容

IdentityServer4 是Asp.net core的一個中間件,用於添加符合OpenId Connect和OAuth2.0規范的終端到Asp.net Core應用。在這里簡單介紹一下Openid和OAuth2.0。

OpenId:用戶身份認證(Authentication )。當用戶(End User)在微信、Google等OpenId提供者(OpenID Provider)平台注冊賬戶時會產生一個身份標識,這個身份標識就是OpenId,當用戶登錄第三方應用(Relying Part)時如果Relying Part支持OpenId登錄,會生成一個帶有重定向地址的Url跳至OpenId Provider平台登錄界面,用戶登錄成功后,根據重定向地址帶着OpenId跳回Relying Part,標識着用戶身份認證成功,該用戶在OpenId Provider平台有注冊。Relying Part根據OpenId自動注冊賬戶,至此身份認證結束。有時Relying Part需要從Openid Provider那獲取該用戶的更多信息或資源,OpenId Provider需要對Relying Part的請求進行授權管理,這時就用要到OAuth2.0。

OAuth2.0:用戶訪問授權(Authorization)。OAuth2.0是一個JWT(Json Web Token ,Json格式Web令牌)解決方案。其最終目的是給用戶一個包含加密令牌的JSON字符串,這個令牌內包含授權信息,決定了該用戶可以訪問那些資源。OAuth2.0協議規定了4種取得令牌的方式,可以參考這篇文章OAuth2.0的四種方式

Openid Connect:實際上就是將Openid與OAuth2.0結合起來,解決身份認證和身份授權的問題。

客戶端模式只對客戶端進行授權,不涉及到用戶信息。如果你的api需要提供到第三方應用,第三方應用自己做用戶授權,不需要用到你的用戶資源,就可以用客戶端模式,只對客戶端進行授權訪問api資源。

二,創建Asp.net Core 項目

微軟提供了一些針對IdentityServer4的項目模板,在命令行中輸入” dotnet new -i IdentityServer4.Templates“即可安裝,安裝好后可以看到當前已安裝的項目模板,其中有一個"is4empty",其實就是一個asp.net core 應用裝了IdentityServer4包。在命令行中輸入:dotnet new is4empty -n Projectname 就會根據這個模板生成一個新項目。下圖是我的項目,一個api客戶端、一個mvc客戶端,一個identityserver4服務端,其中Api客戶端是受保護的Api資源,Mvc客戶端是第三方客戶端,用於訪問被保護的Api客戶端,可以看成是任意后端程序。

  •  配置IdentityServer服務器,如果是用的is4empty模板創建的項目,已經有一些簡單配置,后面我們慢慢深化
  public void ConfigureServices(IServiceCollection services)
        {
            //添加IdentityServer
            var builder = services.AddIdentityServer()
                //身份信息授權資源
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                //API訪問授權資源
                .AddInMemoryApiResources(Config.GetApis())
                //添加客戶端
                .AddInMemoryClients(Config.GetClients());

            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                throw new Exception("need to configure key material");
            }
        }

        public void Configure(IApplicationBuilder app)
        {
            if (Environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //使用IdentityServer中間件
            app.UseIdentityServer();
        }

  為了能更好的查看調試日志,使用窗口調試,可以在Properties/launchSettings.json中可以更改監聽地址,默認為5000

 

 啟動項目后使用瀏覽器打開:http://localhost:5000/.well-known/openid-configuration。可以看到identityserver4的discover說明。

三,配置IdentityServer4

1,添加ApiResource:修改IdentityServer項目的Config類的GetClients方法,添加一個api資源(ApiResource)。每個被保護的API項目必需有對應一個ApiResource,一個ApiResource可以有被多個API標識,客戶端請求令牌時根據ApiResource名稱決定是否有權限訪問這個API。

   public static IEnumerable<ApiResource> GetApis()
        {
            return new ApiResource[] {
                //secretapi:標識名稱,Secret Api:顯示名稱,可以自定義
                new ApiResource("secretapi","Secret Api")
            };
        }

2,添加客戶端模式用戶:定義好ApiResouce后,再來添加一個客戶端,使得這個客戶端可以訪問secretapi這個資源。修改Config類中的GetClients方法,添加一個用戶用於支持客戶端模式的請求。

public static IEnumerable<Client> GetClients()
        {
            return new Client[] {
              
                new Client()
                {
                    //客戶端Id
                     ClientId="apiClientCd",
                     //客戶端密碼
                     ClientSecrets={new Secret("apiSecret".Sha256()) },
                     //客戶端授權類型,ClientCredentials:客戶端憑證方式
                     AllowedGrantTypes=GrantTypes.ClientCredentials,
                     //允許訪問的資源
                     AllowedScopes={
                        "secretapi"
                    }
                }
            };
        }

四,配置API客戶端

1,配置API項目監聽端口和調試方式

2,配置Api項目認證

IdentityApi.Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddAuthentication("Bearer").AddJwtBearer(r => {
                //認證地址
                r.Authority = "http://localhost:5000";
                //權限標識
                r.Audience = "secretapi";
                //是否必需HTTPS
                r.RequireHttpsMetadata = false;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            //使用認證中間件
            app.UseAuthentication();
            app.UseMvcWithDefaultRoute();
        }

3,添加接口:新建一個空的Api控制器(IdentityController),在這個控制器中添加一個Api:GetUserClaims

  [ApiController]
    public class IdentityController : ControllerBase
    {
        [HttpGet]
        [Route("api/identity")]
        [Microsoft.AspNetCore.Authorization.Authorize]
        public object GetUserClaims()
        {
            return User.Claims.Select(r => new { r.Type, r.Value });
        }
    }

這時GetUserClaims這個Api是訪問不了的,用PostMan訪問時返回401未認證狀態

 

 

五,訪問受保護的Api

要訪問上面那個受保護的Api,分為2步,第一步從IdentityServer獲取token,第二步把這個token使用Bearer authorization 方式添加到Http請求頭。

 1,在IdentityMvc項目訪問受保護的Api

IdentityMvc項目安裝一個Nuget包:IdentityModel,這個包對HttpClient對象有擴寫,封裝了一些IdentityServer的常用請求。修改IdentityServer的監聽端口為5002,使用窗口調試。

在IdentityMvc的HomeController.cs新增一個控制器GetData

  public async Task<IActionResult> GetData()
        {
            var client = new HttpClient();
            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
            if (disco.IsError)
                return new JsonResult(new { err=disco.Error});
            var token= await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest() {
                //獲取Token的地址
                Address = disco.TokenEndpoint,
                //客戶端Id
                ClientId = "apiClientCd",
                //客戶端密碼
                ClientSecret = "apiSecret",
                //要訪問的api資源
                Scope = "secretapi"
            });
            if (token.IsError)
                return new JsonResult(new { err = token.Error });
            client.SetBearerToken(token.AccessToken);
            string data = await client.GetStringAsync("https://localhost:5001/api/identity");
            JArray json = JArray.Parse(data);
            return new JsonResult(json); 
        }

訪問https://localhost:5002/home/getdata可以看到已經成功返回數據

 

2,使用原生HTTP請求訪問受保護的Api

 

獲取access_token:直接打開http://localhost:5000/.well-known/openid-configuration,找到token_endpoint節點

使用PostMan對該節點發送如下Post請求獲取access_token

 

 

 

訪問被保護的Api

由於使用的是Bearer認證機制,所以添加一個名為Authorization的Http請求頭,請求頭的內容是字符串“Bearer”+空格+獲取到的Token:Bearer Token

 

下一篇:dentityServer4實現OAuth2.0之密碼模式.

 


免責聲明!

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



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