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

一,準備內容

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

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。ios

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

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

客戶端模式只對客戶端進行受權,不涉及到用戶信息。若是你的api須要提供到第三方應用,第三方應用本身作用戶受權,不須要用到你的用戶資源,就能夠用客戶端模式,只對客戶端進行受權訪問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。mvc

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

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

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之密碼模式.

相關文章
相關標籤/搜索