【WebAPI No.3】API的訪問控制IdentityServer4

介紹:

IdentityServer是一個OpenID Connect提供者 - 它實現了OpenID Connect和OAuth 2.0協議。是一種向客戶發放安全令牌的軟件。html

官網給出的功能解釋是:web

  • 保護您的資源
  • 使用本地賬戶存儲或經過外部身份提供商對用戶進行身份驗證
  • 提供會話管理和單點登陸
  • 管理和認證客戶
  • 向客戶發佈身份和訪問令牌
  • 驗證令牌

IdentityServe4的四種模式:api

  • 受權碼模式(authorization code)
  • 簡化模式(implicit)
  • 密碼模式(resource owner password credentials)
  • 客戶端模式(client credentials)

如下是IdentityServer的一個大體流程圖:安全

 

註冊IdentityServe4認證服務器:

先在asp.net core咱們選中空模版。由於自己寫的業務也很少,只是爲了作token的認證處理,全部建這個作測試比較方便。服務器

建立代碼示例:

何時都不要忘記添加引用哦:app

NuGet命令行:Install-Package IdentityServer4asp.net

固然你也能夠這樣:async

而後建立config.cs類來處理咱們的一些業務:ide

 //定義範圍
        #region 定義要保護的資源(webapi)
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("FirstAPI", "API接口安全測試")
            };
        }
        #endregion

        #region 定義可訪問客戶端
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    //客戶端id自定義
                    ClientId = "YbfTest",

                    AllowedGrantTypes = GrantTypes.ClientCredentials, ////設置模式,客戶端模式

                    // 加密驗證
                    ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256())
                    },

                    // client能夠訪問的範圍,在GetScopes方法定義的名字。
                    AllowedScopes = new List<string>
                    {
                        "FirstAPI"
                    }
                }
            };
        } 
        #endregion
View Code

以上就是一個基本的處理類了。而後咱們開始在Startup.cs 配置IdentityServer4函數

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                 .AddDeveloperSigningCredential()
                 .AddInMemoryApiResources(Config.GetApiResources())  //配置資源               
                 .AddInMemoryClients(Config.GetClients());//配置客戶端
        }
View Code
 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //將IddiTyServer添加到管道中。
            app.UseIdentityServer();

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }
View Code

這樣就能夠啓動項目了,確認項目啓動完成後,還要確認服務是否開啓成功:在地址後增長地址:/.well-known/openid-configuration 例如:

出現以上結果就是啓動成功了。

固然你也可使用postMan測試工具測試:

須要輸入

  • grant_type爲客戶端受權client_credentials,
  • client_idConfig中配置的ClientId
  • Client_Secret爲Config中配置的Secret

例如:

 建立webAPI資源服務器

這個比較簡單了,首先建立一個簡單的webapi程序便可。

仍是老規矩咯iuput,何時都不要忘記引用:

經過nuget添加便可:IdentityServer4.AccessTokenValidation

而後點擊肯定安裝就能夠了。

主要認證註冊服務:

在Startup類裏面的ConfigureServices方法裏面添加註冊

        public void ConfigureServices(IServiceCollection services)
        {
            //註冊IdentityServer 
            services.AddAuthentication(config => {
                config.DefaultScheme = "Bearer"; //這個是access_token的類型,獲取access_token的時候返回參數中的token_type一致
            }).AddIdentityServerAuthentication(option => {
                option.ApiName = "FirstAPI"; //資源名稱,認證服務註冊的資源列表名稱一致,
                option.Authority = "http://127.0.0.1:5000"; //認證服務的url
                option.RequireHttpsMetadata = false; //是否啓用https

            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

而後在在Startup的Configure方法裏配置Authentication中間件:

           //配置Authentication中間件
            app.UseAuthentication();

而後添加一個控制器進行驗證測試:

我這裏寫了一個獲取value值簡單檢測一下。

 // GET api/values
        [HttpGet]
        [Authorize]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

這裏注意要添加[Authorize]特性。用來作驗證是否有權限的。沒有的話,以上作的沒有意義。須要引用命名空間:using Microsoft.AspNetCore.Authorization;

看一下正確的請求結果:

若是不傳token值請求:

 

 

注意這裏就會返回401的未受權狀態。 

建立Client(客戶端)

上面咱們使用的是postman請求的以演示程序是否建立成功,這裏咱們假設一個用戶的使用客戶端,這裏咱們建立一個控制檯來模擬一下真實的小場景。

既然是控制檯就沒什麼好說的直接上代碼main函數:

Task.Run(async () =>
            {
                //從元數據中發現終結點,查找IdentityServer
                var disco = await DiscoveryClient.GetAsync("http://127.0.0.1:5000");
                if (disco.IsError)
                {
                    Console.WriteLine(disco.Error);
                    return;
                }

                //向IdentityServer請求令牌
                var tokenClient = new TokenClient(disco.TokenEndpoint, "YbfTest", "YbfTest123");//請求的客戶資源
                var tokenResponse = await tokenClient.RequestClientCredentialsAsync("FirstAPI");//運行的範圍

                if (tokenResponse.IsError)
                {
                    Console.WriteLine(tokenResponse.Error);
                    return;
                }

                Console.WriteLine(tokenResponse.Json);

                //訪問Api
                var client = new HttpClient();
                //把令牌添加進請求
                //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",tokenResponse.AccessToken);
                //client.SetBearerToken(tokenResponse.AccessToken);
                client.SetToken("Bearer", tokenResponse.AccessToken);

                var response = await client.GetAsync("http://localhost:42033/api/values");
                if (!response.IsSuccessStatusCode)
                {
                    Console.WriteLine(response.StatusCode);
                }
                else
                {
                    var content = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(JArray.Parse(content));
                }
            });

            Console.ReadLine();
View Code

這裏主要介紹一下請求資源時添加令牌主要有三種形式,我都在代碼給出,根據api資源的註冊形式選擇適合的。api的註冊我也寫了兩種形式。主要的區別就是token前面的Bearer,若是想寫成自定義的和默認成Bearer就是這裏的區分。

自定義就要使用:

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",tokenResponse.AccessToken);

若是全局默認的形式就不比每次請求都要添加因此能夠寫成:

client.SetBearerToken(tokenResponse.AccessToken);

運行項目以後出現成功界面:

 

 傳送門

WebApi系列文章目錄介紹

相關文章
相關標籤/搜索