1. 程式人生 > >.NetCore原始碼閱讀筆記系列之HttpAbstractions(五) Authentication

.NetCore原始碼閱讀筆記系列之HttpAbstractions(五) Authentication

說道認證&授權其實這塊才是核心,這款跟前面Security這塊有者緊密的聯絡,當然 HttpAbstractions 不光是認證、授權、還包含其他Http服務和中間價

接下來先就認證這塊結合前面的Security作一個補充說明

前面 AddCookie 、OpenIdConnect、Google、QQ 等等不過是新增的認證策略方式,他們實現的授權介面都來至於我們的HttpAbstractions模組中的Authentication

只不過前面封裝了擴充套件,看上起好像有點繞,比如OpenIdConnect我們來看下

builder.AddRemoteScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, displayName, configureOptions);

我之前說了的OpenIdConnectHandler的重要性,這個其實只不過實現了HttpAbstractions 模組下 Authentication中的抽象模組中的類及認證介面服務提供實現,可以看到OpenIdConnet 新增的遠端認證策略AddRemoteScheme,實際就是 HttpAbstractions 中Authentication中的IAuthenticationHandler介面處理以及先關IAuthenticationSignInHandler、IAuthenticationSignOutHandler的實現,包括在OpenIdConnect 或者 Cookies等裡面呼叫的SignIn SginOut 等操作,而通過下面的程式碼來實現

await handler.SignInAsync(principal, properties);

這裡有一些疑問就是hanlder 是什麼呢?這裡就是提到前面的 AddScheme中策略問題了,其實就是提供認證處理介面

public IAuthenticationHandlerProvider Handlers { get; }

說道這裡,就需要提到軟體設計中經常會用到的一個步驟,那就是 Build 、Provider 、Handler  看到這三個東西是不是很熟悉

接下來我們來看下 AuthenticationSchemeBuilder 中的 Build構建,構建的時候指定了HandlerType ,其實這裡的 HandlerType就是在AddScheme中指定了具體處理方式,注意這裡的指定方式需要繼承IAuthenticationHandler,當然也是在這裡去構建

public void AddScheme<THandler>(string name, string displayName) where THandler : IAuthenticationHandler
            => AddScheme(name, b =>
            {
                b.DisplayName = displayName;
                b.HandlerType = typeof(THandler);
            });

其實我們可以這樣來描述,我們現在在ConfigureServices新增好自己授權服務,假定我們沒有引數,結合之前的OpenIdConnect例子,AddAuthenticationCore 、AddAuthentication其實都是擴充套件方法而已,裡面其實實現了

IAuthenticationService 、IAuthenticationHandlerProvider、IAuthenticationSchemeProvider等服務的註冊,下面我們這樣來寫,這裡的CustomHandler是我自定義的處理策略handlertype,當然這裡需要實現介面IAuthenticationHandler,當然還可以實現簽入、簽出相關介面

services.AddAuthenticationCore(options =>
            {
                options.AddScheme<CustomHandler>("name", "displayname");

            });
public class CustomHandler : IAuthenticationHandler
        {
            public Task<AuthenticateResult> AuthenticateAsync()
            {
                throw new NotImplementedException();
            }

            public Task ChallengeAsync(AuthenticationProperties properties)
            {
                throw new NotImplementedException();
            }

            public Task ForbidAsync(AuthenticationProperties properties)
            {
                throw new NotImplementedException();
            }

            public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
            {
                throw new NotImplementedException();
            }
        }

其實這裡自己封裝成一個類庫其實就是類是AddOpenIdConnect這樣的認證服務中介軟體了,比如我前面寫的 AddCustom,然而你寫了這些之後怎麼來實現認證的呢?

這裡就需要說到 UserAuthentication這個中介軟體了,下面我們來看下這個中介軟體處理什麼? 其實說到這裡就已經很清楚了,就是拿到認證服務提供,呼叫Handler處理認證,然後將認證資訊寫入到User中,下面就是AuthenticationMiddleware中介軟體要做的事情

 var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
            foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
            {
                var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
                if (handler != null && await handler.HandleRequestAsync())
                {
                    return;
                }
            }

            var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
            if (defaultAuthenticate != null)
            {
                var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
                if (result?.Principal != null)
                {
                    context.User = result.Principal;
                }
            }

            await _next(context);

通過這些文字,相信基本多這塊有大志的瞭解了,希望能夠幫助到大家