HTML5技术

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

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

对于上面的前三个方法,我们知道在IAuthenticationHandler中都有对应的实现,而SignInAsync和SignOutAsync则使用了独立的定义接口: public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandl

对于上面的前三个方法,我们知道在IAuthenticationHandler中都有对应的实现,而SignInAsync和SignOutAsync则使用了独立的定义接口:

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

SignInAsync 和 SignOutAsync 之所以使用独立的接口,是因为在现代架构中,通常会提供一个统一的认证中心,负责证书的颁发及销毁(登入和登出),而其它服务只用来验证证书,并用不到SingIn/SingOut。

而 IAuthenticationService 的默认实现 AuthenticationService 中的逻辑就非常简单了,只是调用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中对这5个方法的实现大致相同,首先会在我们传入的scheme为null时,来获取我们所注册的默认scheme,然后获取调用相应Handler的即可。针对 SignInAsync 和 SignOutAsync 的实现则会判断Handler是否实现了对应的接口,若未实现则抛出异常。

不过在这里还涉及到如下两个对象:

AuthenticateResult

AuthenticateResult 用来表示认证的结果:

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

它主要包含一个核心属性 AuthenticationTicket:

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

我们可以把AuthenticationTicket看成是一个经过认证后颁发的证书,

其 ClaimsPrincipal 属性我们较为熟悉,表示证书的主体,在基于声明的认证中,用来标识一个人的身份(如:姓名,邮箱等等),后续会详细介绍一下基于声明的认证。

而 AuthenticationProperties 属性用来表示证书颁发的相关信息,如颁发时间,过期时间,重定向地址等等:

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

在上面最开始介绍的HttpContext中的 GetTokenAsync 扩展方法便是对AuthenticationProperties的扩展:

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扩展只是对AuthenticationProperties中的 Items 属性进行添加和读取。

IClaimsTransformation

 

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

网友点评
r