.NetCore 中介軟體之AddAuthentication服務說明及實現原理簡述
如果你使用過.NetCore開發過程序,你會很清楚,在其中我們經常會用到一些如下的程式碼
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie("Cookies",options=>{
});
然後添加了中介軟體
app.UseAuthentication();
然而這些中間內部、服務之間怎麼去處授權的呢?接下來就來探討一下。
先來說說UseAuthentication這個都做了什麼事情
首先我們先來看下在判斷授權的時候是用HttpContext.User中獲取了身份資訊,從身份中獲取了IsAuthenticated來判斷是否認證,通過這些我們發現其實 UseAuthentication就做了下面的事情,通過app.UseMiddleware<AuthenticationMiddleware>();中介軟體將身份資訊寫入到上下文物件中的User中
context.User = result.Principal;
不然發現在這個過程中,會有一些相關的基礎服務和配置引數,讓後自然而然會想到添加註入服務,然後下面的程式碼就出來了,新增認證服務、以及一些初始引數的配置
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme= CookieAuthenticationDefaults.AuthenticationScheme; });
接下來我們來看一看AddAuthentication幹了什麼事情,寫過擴充套件的朋友都知道,AddAuthentication只是一個掛載到IServiceCollection上的一個擴充套件方法,有引數就想到了配置所裡擴充套件方法裡面就完成了2件事情
var builder = services.AddAuthentication(); services.Configure(configureOptions);
新增授權服務和新增配置服務
這裡的builder其實是AuthenticationBuilder,其實這個類也沒做什麼事情,就接管了下IServiceCollection服務,以便於在AuthenticationBuilder中完成對services服務呼叫完成其他的功能,如AddScheme
public AuthenticationBuilder(IServiceCollection services) => Services = services;
管道中中介軟體像企業的生產流水線一樣,經過一層一層的加工(HttpContext=>HttpRequest、HttpRespose、IFeatureCollection、ClaimsPrincipal)等,最後返回加工好的產品,這裡的認證中介軟體也不例外,主要就是為了附加ClaimsPrincipal而生的
這個圖也不知被用了多少次了,我也用下
接下來就來看下在中介軟體AuthenticationMiddleware中都做了什麼事情
public static IApplicationBuilder UseAuthentication(this IApplicationBuilder app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } return app.UseMiddleware<AuthenticationMiddleware>(); }
說道中介軟體不得不提到一個重要的東東RequestDelegate這個物件,他就想一個包裹的產品,穿梭連線在每個中介軟體遊走,就想生產流水線上的傳送產品的傳送帶一樣,傳送做請求中的各種物件
首先要獲取的就是 提供的授權處理服務 IAuthenticationHandlerProvider
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
這裡還要說下的就是IAuthenticationSchemeProvider,由於授權引數指定的Scheme指定了獲取授權來源,中介軟體需要獲取當前配置的Scheme對應的IAuthenticationHandlerProvider處理服務
如果獲取到就處理授權請求,這裡要說明下程式碼,在.NetCore其他地方對下面處理請求做了介面實現,其實就是AddCookies中的CookieAuthenticationHandler,當找到對應請求就不會在處理了。
public interface IAuthenticationRequestHandler : IAuthenticationHandler { Task<bool> HandleRequestAsync(); }
可以看到這樣的實現,需要什麼實現就新增什麼handle,只是這裡AddCookie幫我們處理了
public class CookieAuthenticationHandler : AuthenticationHandler<CookieAuthenticationOptions>, IAuthenticationSignInHandler, IAuthenticationSignOutHandler { }
如果沒有從授權Scheme中找到,說明未認證,需要新增認證身份資訊的Scheme,獲取到IAuthenticationService服務
context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme);
這裡實際上還是從IAuthenticationHandlerProvider服務提供,只是在IAuthenticationService服務中注入了相關服務,最終還是通過IAuthenticationHandler去實現的
public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform) { /* */ }
那麼登入的時候SignIn做了什麼呢?
context.RequestServices.GetRequiredService<IAuthenticationService>().SignInAsync(context, scheme, principal, properties);
從認證服務中呼叫了SignIn,其實最終都是通過IAuthenticationHandler介面來處理的,SignIn、SignOut都是通過AddCookies中CookieAuthenticationHandler實現了IAuthenticationHandler介面,下面我們針對上面的來畫圖分析下可能要明白一些