ASP.NET Core 实现基于 ApiKey 的认证
ASP.NET Core 實現基于 ApiKey 的認證
Intro
之前我們有介紹過實現基于請求頭的認證,今天來實現一個基于 ApiKey 的認證方式,使用方式參見下面的示例
Sample
注冊認證服務
services.AddAuthentication().AddApiKey(options?=>{options.ApiKey?=?"123456";options.ApiKeyName?=?"X-ApiKey";});可以根據需要是否要指定為默認的認證 Schema
控制器示例代碼:
[HttpGet("apiKeyTest")] [Authorize(AuthenticationSchemes?=?ApiKeyAuthenticationDefaults.AuthenticationSchema)] public?IActionResult?ApiKeyAuthTest() {return?Ok(User.Identity); }因為我們沒有指定為默認的認證 Schema,所以在這個 Action 上我們指定了希望使用的認證方式
調用示例:
直接調用不使用 ApiKey
使用錯誤的 ApiKey
使用正確的 ApiKey
從上面的結果可以看出來只有在 ApiKey 是正確的情況下才能正常調用 Api
Implement
對于自定義認證方式我們之前也有介紹過基于請求頭的認證方式,基于 ApiKey 的認證和請求頭也類似,
對于自定義認證方式,核心需要定義的有兩個類型
- 一個是認證選項,自定義的 AuthenticationOption 
- 一個是認證處理器,自定義的認證處理邏輯 
下面來看實現
ApiKeyAuthenticationOptions
實現如下:
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 并添加認證所需的配置,我們增加了一個 KeyLocation 以配置讀取 ApiKey 的來源,Header 就是從請求頭去讀,Query 就是從查詢字符串讀取,HeaderOrQuery 就是優先讀取 Header,對應的 QueryOrHeader 就是優先讀取查詢字符串
另外我們可以重載 Validate 方法來對我們的配置進行校驗
ApiKeyAuthenticationHandler
認證處理器是認證方式的核心處理邏輯,我們的處理也比較簡單,就是直接讀取 ApiKey 與配置的 ApiKey 對比,一致就認證成功,否則就是非法請求,實現如下:
public?sealed?class?ApiKeyAuthenticationHandler?:?AuthenticationHandler<ApiKeyAuthenticationOptions> {public?ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions>?options,?ILoggerFactory?logger,?UrlEncoder?encoder,?ISystemClock?clock)?:?base(options,?logger,?encoder,?clock){}protected?override?Task<AuthenticateResult>?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
為了方便使用添加了幾個常用的擴展方法,類似于 ASP.NET Core 自帶的認證方式
首先增加了一個默認的認證模式
public?static?class?ApiKeyAuthenticationDefaults {public?const?string?AuthenticationSchema?=?"ApiKey"; }然后增加了一些依賴注入的擴展
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<ApiKeyAuthenticationOptions>?configureOptions) {return?builder.AddApiKey(ApiKeyAuthenticationDefaults.AuthenticationSchema,configureOptions); }public?static?AuthenticationBuilder?AddApiKey(this?AuthenticationBuilder?builder,?string?schema,Action<ApiKeyAuthenticationOptions>?configureOptions) {if?(null?!=?configureOptions){builder.Services.Configure(configureOptions);}return?builder.AddScheme<ApiKeyAuthenticationOptions,?ApiKeyAuthenticationHandler>(schema,configureOptions); }More
目前的實現比較簡單,只是對 ApiKey 做了校驗,而且是直接讀取的配置,大家可以根據自己需要進行一定的擴展,比如 ApiKey 從數據庫中讀取、增加額外的 claim 配置等。
對于一些需要配置客戶端訪問權限的可以使用這種方式來實現簡單的認證來代替基于 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 自定義認證方式--請求頭認證 
總結
以上是生活随笔為你收集整理的ASP.NET Core 实现基于 ApiKey 的认证的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Avalonia跨平台入门第八篇之控件的
- 下一篇: 腾讯急招多名.NET Core,5年30
