HTML5技术

ASP.NET Core 运行原理解剖[5]:Authentication - 雨の夜(2)

字号+ 作者:H5之家 来源:H5之家 2017-09-11 11:16 我要评论( )

如上,通过一个内部的字典来保存我们所注册的Scheme,key为Scheme名称,然后提供一系列对该字典的查询。它还提供了一系列的GetDefaultXXXSchemeAsync方法,所使用的Key是通过构造函数中接收的AuthenticationOptions

如上,通过一个内部的字典来保存我们所注册的Scheme,key为Scheme名称,然后提供一系列对该字典的查询。它还提供了一系列的GetDefaultXXXSchemeAsync方法,所使用的Key是通过构造函数中接收的AuthenticationOptions对象来获取的,如果未配置,则返回为null。

对于 AuthenticationOptions 对象,大家可能会比较熟悉,在上面介绍的 AddAuthenticationCore 扩展方法中,也是使用该对象来配置认证系统:

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; } }

该对象可以帮助我们更加方便的注册Scheme,提供泛型和 AuthenticationSchemeBuilder 两种方式配置方式。

到此,我们了解到,要想使用认证系统,必要先注册Scheme,而每一个Scheme必须指定一个Handler,否则会抛出异常,下面我们就来了解一下Handler。

IAuthenticationHandlerProvider

在 ASP.NET Core 的认证系统中,AuthenticationHandler 负责对用户凭证的验证,它定义了如下接口:

public interface IAuthenticationHandler { Task InitializeAsync(AuthenticationScheme scheme, HttpContext context); Task<AuthenticateResult> AuthenticateAsync(); Task ChallengeAsync(AuthenticationProperties properties); Task ForbidAsync(AuthenticationProperties properties); }

AuthenticationHandler的创建是通过 IAuthenticationHandlerProvider 来完成的:

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

Provider 只定义了一个 GetHandlerAsync 方法,来获取指定的Scheme的Hander,在 ASP.NET Core 中,很多地方都使用了类似的 Provider 模式。

而HandlerProvider的实现,我们通过对上面SchemeProvider的了解,应该可以猜到一二,因为在 AuthenticationScheme 中已经包含了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 获取到当前Scheme,然后先从DI中查找是否有此Scheme中的Handler,如果未注册到DI系统中,则使用 ActivatorUtilities 来创建其实例,并缓存到内部的 _handlerMap 字典中。

IAuthenticationService

IAuthenticationService 本质上是对 IAuthenticationSchemeProvider 和 IAuthenticationHandlerProvider 封装,用来对外提供一个统一的认证服务接口:

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个方法中,都需要接收一个 scheme 参数,因为只有先指定你要使用的认证方式,才能知道该如何进行认证。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 【ASP.NET MVC】View与Controller之间传递数据 - Alan_beijing

    【ASP.NET MVC】View与Controller之间传递数据 - Alan_beijing

    2017-09-10 08:02

  • .NET Core多平台开发体验[4]: Docker - Artech

    .NET Core多平台开发体验[4]: Docker - Artech

    2017-09-07 11:57

  • .NET Core 2.0应用程序大小减少50% - LineZero

    .NET Core 2.0应用程序大小减少50% - LineZero

    2017-09-06 08:05

  • ASP.NET Core MVC – Tag Helper 组件 - Sweet-Tang

    ASP.NET Core MVC – Tag Helper 组件 - Sweet-Tang

    2017-09-01 17:02

网友点评
m