<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ASP.NET Core 實現(xiàn)基于 ApiKey 的認(rèn)證

          共 4918字,需瀏覽 10分鐘

           ·

          2022-03-16 15:19

          ASP.NET Core 實現(xiàn)基于 ApiKey 的認(rèn)證

          Intro

          之前我們有介紹過實現(xiàn)基于請求頭的認(rèn)證,今天來實現(xiàn)一個基于 ApiKey 的認(rèn)證方式,使用方式參見下面的示例

          Sample

          注冊認(rèn)證服務(wù)

          services.AddAuthentication()
          ????.AddApiKey(options?=>
          ????{
          ????????options.ApiKey?=?"123456";
          ????????options.ApiKeyName?=?"X-ApiKey";
          ????});

          可以根據(jù)需要是否要指定為默認(rèn)的認(rèn)證 Schema

          控制器示例代碼:

          [HttpGet("apiKeyTest")]
          [Authorize(AuthenticationSchemes?=?ApiKeyAuthenticationDefaults.AuthenticationSchema)]
          public?IActionResult?ApiKeyAuthTest()
          {
          ????return?Ok(User.Identity);
          }

          因為我們沒有指定為默認(rèn)的認(rèn)證 Schema,所以在這個 Action 上我們指定了希望使用的認(rèn)證方式

          調(diào)用示例:

          直接調(diào)用不使用 ApiKey

          使用錯誤的 ApiKey

          使用正確的 ApiKey

          從上面的結(jié)果可以看出來只有在 ApiKey 是正確的情況下才能正常調(diào)用 Api

          Implement

          對于自定義認(rèn)證方式我們之前也有介紹過基于請求頭的認(rèn)證方式,基于 ApiKey 的認(rèn)證和請求頭也類似,

          對于自定義認(rèn)證方式,核心需要定義的有兩個類型

          • 一個是認(rèn)證選項,自定義的 AuthenticationOption
          • 一個是認(rèn)證處理器,自定義的認(rèn)證處理邏輯

          下面來看實現(xiàn)

          ApiKeyAuthenticationOptions

          實現(xiàn)如下:

          public?sealed?class?ApiKeyAuthenticationOptions?:?AuthenticationSchemeOptions
          {
          ????public?string?ApiKey?{?get;?set;?}
          ????public?string?ApiKeyName?{?get;?set;?}?=?"X-ApiKey";
          ????public?string?ClientId?{?get;?set;?}
          ????public?KeyLocation?KeyLocation?{?get;?set;?}

          ????public?override?void?Validate()
          ????{
          ????????if?(string.IsNullOrWhiteSpace(ApiKey))
          ????????{
          ????????????throw?new?ArgumentException("Invalid?ApiKey?configured");
          ????????}
          ????}
          }

          public?enum?KeyLocation
          {
          ????Header?=?0,
          ????Query?=?1,
          ????HeaderOrQuery?=?2,
          ????QueryOrHeader?=?3,
          }

          繼承于 AuthenticationSchemeOptions 并添加認(rèn)證所需的配置,我們增加了一個 KeyLocation 以配置讀取 ApiKey 的來源,Header 就是從請求頭去讀,Query 就是從查詢字符串讀取,HeaderOrQuery 就是優(yōu)先讀取 Header,對應(yīng)的 QueryOrHeader 就是優(yōu)先讀取查詢字符串

          另外我們可以重載 Validate 方法來對我們的配置進(jìn)行校驗

          ApiKeyAuthenticationHandler

          認(rèn)證處理器是認(rèn)證方式的核心處理邏輯,我們的處理也比較簡單,就是直接讀取 ApiKey 與配置的 ApiKey 對比,一致就認(rèn)證成功,否則就是非法請求,實現(xiàn)如下:

          public?sealed?class?ApiKeyAuthenticationHandler?:?AuthenticationHandler<ApiKeyAuthenticationOptions>
          {
          ????public?ApiKeyAuthenticationHandler(IOptionsMonitor?options,?ILoggerFactory?logger,?UrlEncoder?encoder,?ISystemClock?clock)?:?base(options,?logger,?encoder,?clock)
          ????{
          ????}

          ????protected?override?Task?HandleAuthenticateAsync()
          ????{
          ????????var?authResult?=?HandleAuthenticateInternal();
          ????????return?Task.FromResult(authResult);
          ????}

          ????private?AuthenticateResult?HandleAuthenticateInternal()
          ????{
          ????????StringValues?keyValues;
          ????????var?keyExists?=?Options.KeyLocation?switch
          ????????{
          ????????????KeyLocation.Query?=>?Request.Query.TryGetValue(Options.ApiKeyName,?out?keyValues),
          ????????????KeyLocation.HeaderOrQuery?=>?Request.Headers.TryGetValue(Options.ApiKeyName,?out?keyValues)?||?Request.Query.TryGetValue(Options.ApiKeyName,?out?keyValues),
          ????????????KeyLocation.QueryOrHeader?=>?Request.Query.TryGetValue(Options.ApiKeyName,?out?keyValues)?||?Request.Headers.TryGetValue(Options.ApiKeyName,?out?keyValues),
          ????????????_?=>?Request.Headers.TryGetValue(Options.ApiKeyName,?out?keyValues),
          ????????};
          ????????if?(!keyExists)
          ????????????return?AuthenticateResult.NoResult();

          ????????if?(keyValues.ToString().Equals(Options.ApiKey))
          ????????{
          ????????????var?clientId?=?Options.ClientId.GetValueOrDefault(ApplicationHelper.ApplicationName);
          ????????????return?AuthenticateResult.Success(
          ????????????????new?AuthenticationTicket(
          ????????????????????new?ClaimsPrincipal(new[]
          ????????????????????{
          ????????????????????????????new?ClaimsIdentity(new[]
          ????????????????????????????{
          ????????????????????????????????new?Claim(nameof(Options.ClientId),?clientId,?ClaimValueTypes.String,?ClaimsIssuer),
          ????????????????????????????},?Scheme.Name)
          ????????????????????}),?Scheme.Name)
          ????????????);
          ????????}
          ????????return?AuthenticateResult.Fail("Invalid?Api-Key");
          ????}
          }

          Extensions

          為了方便使用添加了幾個常用的擴(kuò)展方法,類似于 ASP.NET Core 自帶的認(rèn)證方式

          首先增加了一個默認(rèn)的認(rèn)證模式

          public?static?class?ApiKeyAuthenticationDefaults
          {
          ????public?const?string?AuthenticationSchema?=?"ApiKey";
          }

          然后增加了一些依賴注入的擴(kuò)展

          public?static?AuthenticationBuilder?AddApiKey(this?AuthenticationBuilder?builder)
          {
          ????return?builder.AddApiKey(ApiKeyAuthenticationDefaults.AuthenticationSchema);
          }

          public?static?AuthenticationBuilder?AddApiKey(this?AuthenticationBuilder?builder,?string?schema)
          {
          ????return?builder.AddApiKey(schema,?_?=>?{?});
          }

          public?static?AuthenticationBuilder?AddApiKey(this?AuthenticationBuilder?builder,
          ????Action?configureOptions
          )

          {
          ????return?builder.AddApiKey(ApiKeyAuthenticationDefaults.AuthenticationSchema,
          ????????configureOptions);
          }

          public?static?AuthenticationBuilder?AddApiKey(this?AuthenticationBuilder?builder,?string?schema,
          ????Action?configureOptions
          )

          {
          ????if?(null?!=?configureOptions)
          ????{
          ????????builder.Services.Configure(configureOptions);
          ????}
          ????return?builder.AddScheme(schema,
          ????????configureOptions);
          }

          More

          目前的實現(xiàn)比較簡單,只是對 ApiKey 做了校驗,而且是直接讀取的配置,大家可以根據(jù)自己需要進(jìn)行一定的擴(kuò)展,比如 ApiKey 從數(shù)據(jù)庫中讀取、增加額外的 claim 配置等。

          對于一些需要配置客戶端訪問權(quán)限的可以使用這種方式來實現(xiàn)簡單的認(rèn)證來代替基于 OAuth 的 Client Credentials?方式,相對來說會簡單一些

          References

          • https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/src/WeihanLi.Web.Extensions/Authentication/ApiKeyAuthentication/ApiKeyAuthenticationHandler.cs
          • https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/samples/WeihanLi.Web.Extensions.Samples/Program.cs
          • asp.net core 自定義認(rèn)證方式--請求頭認(rèn)證


          瀏覽 67
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本www色| 日日日av| 韩国一级在线看 | 9久精品| 1234无码在线观看 |