日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 运行原理解剖[5]:Authentication

發(fā)布時(shí)間:2023/12/4 asp.net 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 运行原理解剖[5]:Authentication 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在現(xiàn)代應(yīng)用程序中,認(rèn)證已不再是簡(jiǎn)單的將用戶憑證保存在瀏覽器中,而要適應(yīng)多種場(chǎng)景,如App,WebAPI,第三方登錄等等。在 ASP.NET 4.x 時(shí)代的Windows認(rèn)證和Forms認(rèn)證已無(wú)法滿足現(xiàn)代化的需求,因此在ASP.NET Core 中對(duì)認(rèn)證及授權(quán)進(jìn)行了全新設(shè)計(jì),使其更加靈活,可以應(yīng)付各種場(chǎng)景。在上一章中,我們提到HttpContext中認(rèn)證相關(guān)的功能放在了獨(dú)立的模塊中,以擴(kuò)展的方式來(lái)展現(xiàn),以保證HttpContext的簡(jiǎn)潔性,本章就來(lái)介紹一下 ASP.NET Core 認(rèn)證系統(tǒng)的整個(gè)輪廓,以及它的切入點(diǎn)。

AuthenticationHttpContextExtensions

AuthenticationHttpContextExtensions 類是對(duì) HttpContext 認(rèn)證相關(guān)的擴(kuò)展,它提供了如下擴(kuò)展方法:

public static class AuthenticationHttpContextExtensions{ ?

?public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context, string scheme) =>context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme); ? ?public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties) { } ? ?public static Task ForbidAsync(this HttpContext context, string scheme, AuthenticationProperties properties) { } ? ?public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) {} ? ?public static Task SignOutAsync(this HttpContext context, string scheme, AuthenticationProperties properties) { } ? ?public static Task<string> GetTokenAsync(this HttpContext context, string scheme, string tokenName) { } }

主要包括如上6個(gè)擴(kuò)展方法,其它的只是一些參數(shù)重載:

  • SignInAsync?用戶登錄成功后頒發(fā)一個(gè)證書(加密的用戶憑證),用來(lái)標(biāo)識(shí)用戶的身份。

  • SignOutAsync?退出登錄,如清除Coookie等。

  • AuthenticateAsync?驗(yàn)證在?SignInAsync?中頒發(fā)的證書,并返回一個(gè)?AuthenticateResult?對(duì)象,表示用戶的身份。

  • ChallengeAsync?返回一個(gè)需要認(rèn)證的標(biāo)識(shí)來(lái)提示用戶登錄,通常會(huì)返回一個(gè)?401?狀態(tài)碼。

  • ForbidAsync?禁上訪問(wèn),表示用戶權(quán)限不足,通常會(huì)返回一個(gè)?403?狀態(tài)碼。

  • GetTokenAsync?用來(lái)獲取?AuthenticationProperties?中保存的額外信息。

它們的實(shí)現(xiàn)都非常簡(jiǎn)單,與展示的第一個(gè)方法類似,從DI系統(tǒng)中獲取到?IAuthenticationService?接口實(shí)例,然后調(diào)用其同名方法。

因此,如果我們希望使用認(rèn)證服務(wù),那么首先要注冊(cè)?IAuthenticationService?的實(shí)例,ASP.NET Core 中也提供了對(duì)應(yīng)注冊(cè)擴(kuò)展方法:

public static class AuthenticationCoreServiceCollectionExtensions{ ? ?public static IServiceCollection AddAuthenticationCore(this IServiceCollection services) ? ?{services.TryAddScoped<IAuthenticationService, AuthenticationService>();services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>(); // Can be replaced with scoped ones that use DbContextservices.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>(); ? ?
? ?return services;} ? ?
? ?
? ?public static IServiceCollection AddAuthenticationCore(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) ? ?{services.AddAuthenticationCore();services.Configure(configureOptions); ? ? ?
? ? ?return services;} }

如上,AddAuthenticationCore?中注冊(cè)了認(rèn)證系統(tǒng)的三大核心對(duì)象:IAuthenticationSchemeProvider,IAuthenticationHandlerProvider?和?IAuthenticationService,以及一個(gè)對(duì)Claim進(jìn)行轉(zhuǎn)換的 IClaimsTransformation(不常用),下面就來(lái)介紹一下這三大對(duì)象。

IAuthenticationSchemeProvider

首先來(lái)解釋一下?Scheme?是用來(lái)做什么的。因?yàn)樵?ASP.NET Core 中可以支持各種各樣的認(rèn)證方式(如,cookie, bearer, oauth, openid 等等),而 Scheme 用來(lái)標(biāo)識(shí)使用的是哪種認(rèn)證方式,不同的認(rèn)證方式其處理方式是完全不一樣的,所以Scheme是非常重要的。

IAuthenticationSchemeProvider 用來(lái)提供對(duì)Scheme的注冊(cè)和查詢,定義如下:

public interface IAuthenticationSchemeProvider{ ?

?void AddScheme(AuthenticationScheme scheme); ? ?
?Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync(); ? ?
?Task<AuthenticationScheme> GetSchemeAsync(string name); ? ?
?Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync(); ?
?Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync(); ?
?Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync(); ? ?Task<AuthenticationScheme> GetDefaultForbidSchemeAsync(); ? ?Task<AuthenticationScheme> GetDefaultSignInSchemeAsync(); ?
?Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync(); }

其?AddScheme?方法,用來(lái)注冊(cè)Scheme,而每一種Scheme最終體現(xiàn)為一個(gè)?AuthenticationScheme?類型的對(duì)象:

public class AuthenticationScheme{ ?

?public AuthenticationScheme(string name, string displayName, Type handlerType) ? ?{ ? ? ?
? ?if (!typeof(IAuthenticationHandler).IsAssignableFrom(handlerType)){ ? ? ? ? ?
? ??throw new ArgumentException("handlerType must implement IAuthenticationSchemeHandler.");}...} ? ?public string Name { get; } ? ?public string DisplayName { get; } ? ?public Type HandlerType { get; } }

每一個(gè)Scheme中還包含一個(gè)對(duì)應(yīng)的IAuthenticationHandler類型的Handler,由它來(lái)完成具體的處理邏輯,看一下它的默認(rèn)實(shí)現(xiàn):

public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider{ ?
?private IDictionary<string, AuthenticationScheme> _map = new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal); ?
?
? ?public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options) ? ?{_options = options.Value; ? ?
? ?? ?foreach (var builder in _options.Schemes){ ? ? ? ? ?
? ?? ? ?var scheme = builder.Build();AddScheme(scheme);}} ?
? ?
? ??private Task<AuthenticationScheme> GetDefaultSchemeAsync() ? ? ? ?=> _options.DefaultScheme != null? GetSchemeAsync(_options.DefaultScheme): Task.FromResult<AuthenticationScheme>(null);.... }

如上,通過(guò)一個(gè)內(nèi)部的字典來(lái)保存我們所注冊(cè)的Scheme,key為Scheme名稱,然后提供一系列對(duì)該字典的查詢。它還提供了一系列的GetDefaultXXXSchemeAsync方法,所使用的Key是通過(guò)構(gòu)造函數(shù)中接收的AuthenticationOptions對(duì)象來(lái)獲取的,如果未配置,則返回為null。

對(duì)于?AuthenticationOptions?對(duì)象,大家可能會(huì)比較熟悉,在上面介紹的?AddAuthenticationCore?擴(kuò)展方法中,也是使用該對(duì)象來(lái)配置認(rèn)證系統(tǒng):

public class AuthenticationOptions{ ?

?private readonly IList<AuthenticationSchemeBuilder> _schemes = new List<AuthenticationSchemeBuilder>(); ? ?
?
?public IEnumerable<AuthenticationSchemeBuilder> Schemes => _schemes; ?
?
? ?public IDictionary<string, AuthenticationSchemeBuilder> SchemeMap { get; } = new Dictionary<string, AuthenticationSchemeBuilder>(StringComparer.Ordinal); ?
? ?
? ??public void AddScheme(string name, Action<AuthenticationSchemeBuilder> configureBuilder) ? ?{ ? ? ?
? ???if (SchemeMap.ContainsKey(name)){ ? ? ? ? ?
? ????throw new InvalidOperationException("Scheme already exists: " + name);} ? ? ?
? ?????var builder = new AuthenticationSchemeBuilder(name);configureBuilder(builder);_schemes.Add(builder);SchemeMap[name] = builder;} ? ?
? ?
? ?public void AddScheme<THandler>(string name, string displayName) where THandler : IAuthenticationHandler=> AddScheme(name, b =>{b.DisplayName = displayName;b.HandlerType = typeof(THandler);}); ?
? ?
? ?public string DefaultScheme { get; set; } ?
? ?
? ? ?public string DefaultAuthenticateScheme { get; set; } ?
? ? ? ?public string DefaultSignInScheme { get; set; } ?
? ? ? ?
? ? ? ??public string DefaultSignOutScheme { get; set; }
? ? ? ??
? ?? ?public string DefaultChallengeScheme { get; set; } ?
? ?? ?
? ? ?public string DefaultForbidScheme { get; set; } }

該對(duì)象可以幫助我們更加方便的注冊(cè)Scheme,提供泛型和?AuthenticationSchemeBuilder?兩種方式配置方式。

到此,我們了解到,要想使用認(rèn)證系統(tǒng),必要先注冊(cè)Scheme,而每一個(gè)Scheme必須指定一個(gè)Handler,否則會(huì)拋出異常,下面我們就來(lái)了解一下Handler。

IAuthenticationHandlerProvider

在 ASP.NET Core 的認(rèn)證系統(tǒng)中,AuthenticationHandler 負(fù)責(zé)對(duì)用戶憑證的驗(yàn)證,它定義了如下接口:

public interface IAuthenticationHandler{ ?

?Task InitializeAsync(AuthenticationScheme scheme, HttpContext context); ? ?Task<AuthenticateResult> AuthenticateAsync(); ?
?
??Task ChallengeAsync(AuthenticationProperties properties); ?
??
???Task ForbidAsync(AuthenticationProperties properties); }

AuthenticationHandler的創(chuàng)建是通過(guò)?IAuthenticationHandlerProvider?來(lái)完成的:

public interface IAuthenticationHandlerProvider{ ? ?Task<IAuthenticationHandler> GetHandlerAsync(HttpContext context, string authenticationScheme); }

Provider 只定義了一個(gè)?GetHandlerAsync?方法,來(lái)獲取指定的Scheme的Hander,在 ASP.NET Core 中,很多地方都使用了類似的?Provider?模式。

而HandlerProvider的實(shí)現(xiàn),我們通過(guò)對(duì)上面SchemeProvider的了解,應(yīng)該可以猜到一二,因?yàn)樵?AuthenticationScheme?中已經(jīng)包含了Hander:

public class AuthenticationHandlerProvider : IAuthenticationHandlerProvider{ ? ?

public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes) ? ?{Schemes = schemes;} ?

?public IAuthenticationSchemeProvider Schemes { get; } ?
?
??private Dictionary<string, IAuthenticationHandler> _handlerMap = new Dictionary<string, IAuthenticationHandler>(StringComparer.Ordinal); ? ?
??
??public async Task<IAuthenticationHandler> GetHandlerAsync(HttpContext context, string authenticationScheme) ? ?{ ?
??? ? ?if (_handlerMap.ContainsKey(authenticationScheme)){ ? ? ? ? ?
??? ? ??return _handlerMap[authenticationScheme];} ? ? ?
??? ? ???var scheme = await Schemes.GetSchemeAsync(authenticationScheme); ? ? ? ?if (scheme == null){ ? ? ? ? ?
??? ? ??? ?return null;} ? ? ? ?var handler = (context.RequestServices.GetService(scheme.HandlerType) ??ActivatorUtilities.CreateInstance(context.RequestServices, scheme.HandlerType)) ? ? ? ? ? ?as IAuthenticationHandler; ? ? ? ?if (handler != null){ ? ? ? ? ? ?await handler.InitializeAsync(scheme, context);_handlerMap[authenticationScheme] = handler;} ? ? ? ?return handler;} }

可以看到,AuthenticationHandlerProvider?首先使用?IAuthenticationSchemeProvider?獲取到當(dāng)前Scheme,然后先從DI中查找是否有此Scheme中的Handler,如果未注冊(cè)到DI系統(tǒng)中,則使用?ActivatorUtilities?來(lái)創(chuàng)建其實(shí)例,并緩存到內(nèi)部的?_handlerMap?字典中。

IAuthenticationService

IAuthenticationService 本質(zhì)上是對(duì) IAuthenticationSchemeProvider 和 IAuthenticationHandlerProvider 封裝,用來(lái)對(duì)外提供一個(gè)統(tǒng)一的認(rèn)證服務(wù)接口:

public interface IAuthenticationService{ ?

?Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme); ? ?
?
?Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties); ?
?
?Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties); ?
?
?Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties);
?
?Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties); }

這5個(gè)方法中,都需要接收一個(gè)?scheme?參數(shù),因?yàn)橹挥邢戎付阋褂玫恼J(rèn)證方式,才能知道該如何進(jìn)行認(rèn)證。

對(duì)于上面的前三個(gè)方法,我們知道在IAuthenticationHandler中都有對(duì)應(yīng)的實(shí)現(xiàn),而SignInAsync和SignOutAsync則使用了獨(dú)立的定義接口:

public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandler{ ?
??Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties); }
??
??public interface IAuthenticationSignOutHandler : IAuthenticationHandler{ ? ?Task SignOutAsync(AuthenticationProperties properties); }

SignInAsync 和 SignOutAsync 之所以使用獨(dú)立的接口,是因?yàn)樵诂F(xiàn)代架構(gòu)中,通常會(huì)提供一個(gè)統(tǒng)一的認(rèn)證中心,負(fù)責(zé)證書的頒發(fā)及銷毀(登入和登出),而其它服務(wù)只用來(lái)驗(yàn)證證書,并用不到SingIn/SingOut。

而 IAuthenticationService 的默認(rèn)實(shí)現(xiàn) AuthenticationService 中的邏輯就非常簡(jiǎn)單了,只是調(diào)用Handler中的同名方法:

public class AuthenticationService : IAuthenticationService{ ?

?public IAuthenticationSchemeProvider Schemes { get; } ? ?
?
?public IAuthenticationHandlerProvider Handlers { get; } ?
?
?public IClaimsTransformation Transform { get; } ?
?
?public virtual async Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme) ? ?{ ? ?
? ? ?if (scheme == null){ ? ? ? ? ?
? ? ? ? ??var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync();scheme = defaultScheme?.Name; ? ? ?
? ? ? ? ???if (scheme == null){ ? ? ? ? ? ? ?
? ? ? ? ??? ? ?throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found.");}} ? ? ?
? ? ??var handler = await Handlers.GetHandlerAsync(context, scheme);
? ? ??var result = await handler.AuthenticateAsync(); ? ? ?
? ? ??if (result != null && result.Succeeded){ ? ? ? ? ?
? ? ?? ? ??var transformed = await Transform.TransformAsync(result.Principal); ? ? ? ? ?
? ? ?? ? ?return AuthenticateResult.Success(new AuthenticationTicket(transformed, result.Properties, result.Ticket.AuthenticationScheme));} ? ? ?
? ? ???return result;} }

AuthenticationService中對(duì)這5個(gè)方法的實(shí)現(xiàn)大致相同,首先會(huì)在我們傳入的scheme為null時(shí),來(lái)獲取我們所注冊(cè)的默認(rèn)scheme,然后獲取調(diào)用相應(yīng)Handler的即可。針對(duì)?SignInAsync?和?SignOutAsync?的實(shí)現(xiàn)則會(huì)判斷Handler是否實(shí)現(xiàn)了對(duì)應(yīng)的接口,若未實(shí)現(xiàn)則拋出異常。

不過(guò)在這里還涉及到如下兩個(gè)對(duì)象:

AuthenticateResult

AuthenticateResult 用來(lái)表示認(rèn)證的結(jié)果:

public class AuthenticateResult{ ?
?public AuthenticationTicket Ticket { get; protected set; } ?
? ? ? public bool Succeeded => Ticket != null; ?
? ? ??public ClaimsPrincipal Principal => Ticket?.Principal; ?
? ?? ?public AuthenticationProperties Properties => Ticket?.Properties; ? ? ? ? ? ? ? ? ?
? ?? ?public Exception Failure { get; protected set; }
? ?? ?public bool None { get; protected set; } ?
? ?? ?
? ?? ?public static AuthenticateResult Success(AuthenticationTicket ticket) => new AuthenticateResult() { Ticket = ticket };
? ??
? ?? ?public static AuthenticateResult NoResult() => new AuthenticateResult() { None = true };
? ?? ?
? ?? ?public static AuthenticateResult Fail(Exception failure) => new AuthenticateResult() { Failure = failure };
? ?? ?
? ?? ?public static AuthenticateResult Fail(string failureMessage) => new AuthenticateResult() { Failure = new Exception(failureMessage) }; }

它主要包含一個(gè)核心屬性?AuthenticationTicket:

public class AuthenticationTicket{ public string AuthenticationScheme { get; private set; } ?
?public ClaimsPrincipal Principal { get; private set; } ?
? ?public AuthenticationProperties Properties { get; private set; } }

我們可以把AuthenticationTicket看成是一個(gè)經(jīng)過(guò)認(rèn)證后頒發(fā)的證書,

其?ClaimsPrincipal?屬性我們較為熟悉,表示證書的主體,在基于聲明的認(rèn)證中,用來(lái)標(biāo)識(shí)一個(gè)人的身份(如:姓名,郵箱等等),后續(xù)會(huì)詳細(xì)介紹一下基于聲明的認(rèn)證。

而?AuthenticationProperties?屬性用來(lái)表示證書頒發(fā)的相關(guān)信息,如頒發(fā)時(shí)間,過(guò)期時(shí)間,重定向地址等等:

public class AuthenticationProperties{ ?

?public IDictionary<string, string> Items { get; } ?
?
? ?public string RedirectUri{ ? ? ?
? ??get{ ? ? ? ? ?
? ???string value; ? ? ? ? ?
? ??? ?return Items.TryGetValue(RedirectUriKey, out value) ? value : null;} ? ? ?
? ??? ??set{ ? ? ? ? ?
? ??? ?? ?if (value != null) Items[RedirectUriKey] = value; ?
? ??? ?? ??else{ ? ? ? ? ? ?
? ??? ?? ?? ? ?if (Items.ContainsKey(RedirectUriKey)) Items.Remove(RedirectUriKey);}}}... }

在上面最開(kāi)始介紹的HttpContext中的?GetTokenAsync?擴(kuò)展方法便是對(duì)AuthenticationProperties的擴(kuò)展:

public static class AuthenticationTokenExtensions{ ?

?private static string TokenNamesKey = ".TokenNames"; ?
??private static string TokenKeyPrefix = ".Token."; ? ?
??public static void StoreTokens(this AuthenticationProperties properties, IEnumerable<AuthenticationToken> tokens) {} ?
??public static bool UpdateTokenValue(this AuthenticationProperties properties, string tokenName, string tokenValue) {} ?
??public static IEnumerable<AuthenticationToken> GetTokens(this AuthenticationProperties properties) { } ?
??public static string GetTokenValue(this AuthenticationProperties properties, string tokenName) ? ?{ ? ? ?
???var tokenKey = TokenKeyPrefix + tokenName; ?
??? ? ? ?return properties.Items.ContainsKey(tokenKey) ? properties.Items[tokenKey] : null;} ?
?public static Task<string> GetTokenAsync(this IAuthenticationService auth, HttpContext context, string tokenName) ? ? ? ?=> auth.GetTokenAsync(context, scheme: null, tokenName: tokenName); ? ?
?public static async Task<string> GetTokenAsync(this IAuthenticationService auth, HttpContext context, string scheme, string tokenName) ?
?
{ ?
?? ? ?var result = await auth.AuthenticateAsync(context, scheme); ? ? ? ?return result?.Properties?.GetTokenValue(tokenName);} }

如上,Token擴(kuò)展只是對(duì)AuthenticationProperties中的?Items?屬性進(jìn)行添加和讀取。

IClaimsTransformation

IClaimsTransformation 用來(lái)對(duì)由我們的應(yīng)用程序傳入的?ClaimsPrincipal?進(jìn)行轉(zhuǎn)換,它只定義了一個(gè)?Transform?方法:

public interface IClaimsTransformation{ ?
?Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal); }

其默認(rèn)實(shí)現(xiàn),不做任何處理,直接返回。它適合于全局的為?ClaimsPrincipal?添加一些預(yù)定義的聲明,如添加當(dāng)前時(shí)間等,然后在DI中把我們的實(shí)現(xiàn)注冊(cè)進(jìn)去即可。

Usage

下面我們演示一下 ASP.NET Core 認(rèn)證系統(tǒng)的實(shí)際用法:

首先,我們要定義一個(gè)Handler:

public class MyHandler : IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler{ ?

?public AuthenticationScheme Scheme { get; private set; } ?
?
? ?protected HttpContext Context { get; private set; } ?
? ?
? ??public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) ? ?{Scheme = scheme;Context = context; ? ? ? ?return Task.CompletedTask;} ?

?public async Task<AuthenticateResult> AuthenticateAsync() ? ?{ ?
? ? ? ?var cookie = Context.Request.Cookies["mycookie"]; ?
? ? ? ?if (string.IsNullOrEmpty(cookie)){ ? ? ? ?
? ?return AuthenticateResult.NoResult();} ? ? ?
? ??return AuthenticateResult.Success(Deserialize(cookie));} ? ?

public Task ChallengeAsync(AuthenticationProperties properties) ? ?{Context.Response.Redirect("/login"); ? ? ? ?return Task.CompletedTask;} ?

?public Task ForbidAsync(AuthenticationProperties properties) ? ?{Context.Response.StatusCode = 403; ? ? ? ?return Task.CompletedTask;} ?

?public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) ? ?{ ? ? ?
?var ticket = new AuthenticationTicket(user, properties, Scheme.Name);Context.Response.Cookies.Append("myCookie", Serialize(ticket)); ? ? ? ?return Task.CompletedTask;} ? ?
?
?public Task SignOutAsync(AuthenticationProperties properties) ? ?{Context.Response.Cookies.Delete("myCookie"); ? ?
? ? ?return Task.CompletedTask;} }

如上,在?SignInAsync?中將用戶的Claim序列化后保存到Cookie中,在?AuthenticateAsync?中從Cookie中讀取并反序列化成用戶Claim。

然后在DI系統(tǒng)中注冊(cè)我們的Handler和Scheme:

public void ConfigureServices(IServiceCollection services){services.AddAuthenticationCore(options => options.AddScheme<MyHandler>("myScheme", "demo scheme")); }

最后,便可以通過(guò)HttpContext來(lái)調(diào)用認(rèn)證系統(tǒng)了:

public void Configure(IApplicationBuilder app){ ?
?// 登錄app.Map("/login", builder => builder.Use(next =>{ ? ? ?
??return async (context) =>{ ? ? ? ?
??? ?var claimIdentity = new ClaimsIdentity(); ? ? ? ? ?
??? ??claimIdentity.AddClaim(new Claim(ClaimTypes.Name, "jim")); ? ? ? ? ? ?await context.SignInAsync("myScheme", new ClaimsPrincipal(claimIdentity));};})); ?
??? ???// 退出app.Map("/logout", builder => builder.Use(next =>{ ? ? ?
??? ????return async (context) =>{ ? ? ? ? ?
??? ?????await context.SignOutAsync("myScheme");};})); ? ?// 認(rèn)證app.Use(next =>{ ? ? ? ?
??? ?????return async (context) =>{ ? ? ? ? ? ?
??? ?????var result = await context.AuthenticateAsync("myScheme"); ? ? ? ?
??? ????? ? ?if (result?.Principal != null) context.User = result.Principal; ? ? ? ? ?
??? ????? ? ? ?await next(context);};}); ? ?// 授權(quán)app.Use(async (context, next) =>{ ?
?
??? ??? ?var user = context.User; ?
??? ????if (user?.Identity?.IsAuthenticated ?? false){ ? ? ?
??? ????if (user.Identity.Name != "jim") await context.ForbidAsync("myScheme"); ? ?
?? ? ? ?else await next();} ? ? ? ?
?? ? ? ?else{ ? ? ? ? ?
?? ? ? ??await context.ChallengeAsync("myScheme");}}); ? ?// 訪問(wèn)受保護(hù)資源app.Map("/resource", builder => builder.Run(async (context) => await context.Response.WriteAsync("Hello, ASP.NET Core!"))); }

在這里完整演示了 ASP.NET Core 認(rèn)證系統(tǒng)的基本用法,當(dāng)然,在實(shí)際使用中要比這更加復(fù)雜,如安全性,易用性等方面的完善,但本質(zhì)上也就這么多東西。

總結(jié)

本章基于?HttpAbstractions?對(duì) ASP.NET Core 認(rèn)證系統(tǒng)做了一個(gè)簡(jiǎn)單的介紹,但大多是一些抽象層次的定義,并未涉及到具體的實(shí)現(xiàn)。因?yàn)楝F(xiàn)實(shí)中有各種各樣的場(chǎng)景無(wú)法預(yù)測(cè),HttpAbstractions?提供了統(tǒng)一的認(rèn)證規(guī)范,在我們的應(yīng)用程序中,可以根據(jù)具體需求來(lái)靈活的擴(kuò)展適合的認(rèn)證方式。不過(guò)在?Security?提供了更加具體的實(shí)現(xiàn)方式,也包含了 Cookie, JwtBearer, OAuth, OpenIdConnect 等較為常用的認(rèn)證實(shí)現(xiàn)。在下個(gè)系列會(huì)來(lái)詳細(xì)介紹一下 ASP.NET Core 的認(rèn)證與授權(quán),更加偏向于實(shí)戰(zhàn),敬請(qǐng)期待!

ASP.NET Core 在GitHub上的開(kāi)源地址為:https://github.com/aspnet,包含了100多個(gè)項(xiàng)目,ASP.NET Core 的核心是?HttpAbstractions?,其它的都是圍繞著?HttpAbstractions?進(jìn)行的擴(kuò)展。本系列文章所涉及到的源碼只包含?Hosting?和?HttpAbstractions?,它們兩個(gè)已經(jīng)構(gòu)成了一個(gè)完整的 ASP.NET Core 運(yùn)行時(shí),不需要其它模塊,就可以輕松應(yīng)對(duì)一些簡(jiǎn)單的場(chǎng)景。當(dāng)然,更多的時(shí)候我們還會(huì)使用比較熟悉的?Mvc?來(lái)大大提高開(kāi)發(fā)速度和體驗(yàn),后續(xù)再來(lái)介紹一下MVC的運(yùn)行方式。

相關(guān)文章:?

  • .NET Core 2.0 正式發(fā)布信息匯總

  • .NET Standard 2.0 特性介紹和使用指南

  • .NET Core 2.0 的dll實(shí)時(shí)更新、https、依賴包變更問(wèn)題及解決

  • .NET Core 2.0 特性介紹和使用指南

  • Entity Framework Core 2.0 新特性

  • 體驗(yàn) PHP under .NET Core

  • .NET Core 2.0使用NLog

  • 升級(jí)項(xiàng)目到.NET Core 2.0,在Linux上安裝Docker,并成功部署

  • 解決Visual Studio For Mac Restore失敗的問(wèn)題

  • ASP.NET Core 2.0 特性介紹和使用指南

  • .Net Core下通過(guò)Proxy 模式 使用 WCF

  • .NET Core 2.0 開(kāi)源Office組件 NPOI

  • ASP.NET Core Razor頁(yè)面 vs MVC

  • Razor Page–Asp.Net Core 2.0新功能 ?Razor Page介紹

  • MySql 使用 EF Core 2.0 CodeFirst、DbFirst、數(shù)據(jù)庫(kù)遷移(Migration)介紹及示例

  • .NET Core 2.0遷移技巧之web.config配置文件

  • asp.net core MVC 過(guò)濾器之ExceptionFilter過(guò)濾器(一)

  • ASP.NET Core 使用Cookie驗(yàn)證身份

  • ASP.NET Core MVC – Tag Helpers 介紹

  • ASP.NET Core MVC – Caching Tag Helpers

  • ASP.NET Core MVC – Form Tag Helpers

  • ASP.NET Core MVC – 自定義 Tag Helpers

  • ASP.NET Core MVC – Tag Helper 組件

  • ASP.NET Core 運(yùn)行原理解剖[1]:Hosting

  • ASP.NET Core 運(yùn)行原理解剖[2]:Hosting補(bǔ)充之配置介紹

  • ASP.NET Core 運(yùn)行原理解剖[3]:Middleware-請(qǐng)求管道的構(gòu)成

  • ASP.NET Core 運(yùn)行原理解剖[4]:進(jìn)入HttpContext的世界

原文地址:http://www.cnblogs.com/RainingNight/p/authentication-in-asp-net-core.html


.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注

總結(jié)

以上是生活随笔為你收集整理的ASP.NET Core 运行原理解剖[5]:Authentication的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。