zoukankan      html  css  js  c++  java
  • 1.1AuthenticationService【AuthenticationService=>IAuthenticationHandlerProvider>IAuthenticationHandler】

    AuthenticationService=>IAuthenticationHandlerProvider->IAuthenticationHandler
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    
    namespace Microsoft.AspNetCore.Authentication
    {
        /// <summary>
        /// Used to provide authentication.
        /// </summary>
        public interface IAuthenticationService
        {
            /// <summary>
            /// Authenticate for the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <returns>The result.</returns>
            Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string? scheme);
    
            /// <summary>
            /// Challenge the specified authentication scheme.
            /// An authentication challenge can be issued when an unauthenticated user requests an endpoint that requires authentication.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            Task ChallengeAsync(HttpContext context, string? scheme, AuthenticationProperties? properties);
    
            /// <summary>
            /// Forbids the specified authentication scheme.
            /// Forbid is used when an authenticated user attempts to access a resource they are not permitted to access.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            Task ForbidAsync(HttpContext context, string? scheme, AuthenticationProperties? properties);
    
            /// <summary>
            /// Sign a principal in for the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="principal">The <see cref="ClaimsPrincipal"/> to sign in.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            Task SignInAsync(HttpContext context, string? scheme, ClaimsPrincipal principal, AuthenticationProperties? properties);
    
            /// <summary>
            /// Sign out the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            Task SignOutAsync(HttpContext context, string? scheme, AuthenticationProperties? properties);
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Options;
    
    namespace Microsoft.AspNetCore.Authentication
    {
        /// <summary>
        /// Implements <see cref="IAuthenticationService"/>.
        /// </summary>
        public class AuthenticationService : IAuthenticationService
        {
            private HashSet<ClaimsPrincipal>? _transformCache;
    
            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="schemes">The <see cref="IAuthenticationSchemeProvider"/>.</param>
            /// <param name="handlers">The <see cref="IAuthenticationHandlerProvider"/>.</param>
            /// <param name="transform">The <see cref="IClaimsTransformation"/>.</param>
            /// <param name="options">The <see cref="AuthenticationOptions"/>.</param>
            public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform, IOptions<AuthenticationOptions> options)
            {
                Schemes = schemes;
                Handlers = handlers;
                Transform = transform;
                Options = options.Value;
            }
    
            /// <summary>
            /// Used to lookup AuthenticationSchemes.
            /// </summary>
            public IAuthenticationSchemeProvider Schemes { get; }
    
            /// <summary>
            /// Used to resolve IAuthenticationHandler instances.
            /// </summary>
            public IAuthenticationHandlerProvider Handlers { get; }
    
            /// <summary>
            /// Used for claims transformation.
            /// </summary>
            public IClaimsTransformation Transform { get; }
    
            /// <summary>
            /// The <see cref="AuthenticationOptions"/>.
            /// </summary>
            public AuthenticationOptions Options { get; }
    
            /// <summary>
            /// Authenticate for the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <returns>The result.</returns>
            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. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).");
                    }
                }
    
                var handler = await Handlers.GetHandlerAsync(context, scheme);
                if (handler == null)
                {
                    throw await CreateMissingHandlerException(scheme);
                }
    
                // Handlers should not return null, but we'll be tolerant of null values for legacy reasons.
                var result = (await handler.AuthenticateAsync()) ?? AuthenticateResult.NoResult();
    
                if (result.Succeeded)
                {
                    var principal = result.Principal!;
                    var doTransform = true;
                    _transformCache ??= new HashSet<ClaimsPrincipal>();
                    if (_transformCache.Contains(principal))
                    {
                        doTransform = false;
                    }
    
                    if (doTransform)
                    {
                        principal = await Transform.TransformAsync(principal);
                        _transformCache.Add(principal);
                    }
                    return AuthenticateResult.Success(new AuthenticationTicket(principal, result.Properties, result.Ticket!.AuthenticationScheme));
                }
                return result;
            }
    
            /// <summary>
            /// Challenge the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            public virtual async Task ChallengeAsync(HttpContext context, string? scheme, AuthenticationProperties? properties)
            {
                if (scheme == null)
                {
                    var defaultChallengeScheme = await Schemes.GetDefaultChallengeSchemeAsync();
                    scheme = defaultChallengeScheme?.Name;
                    if (scheme == null)
                    {
                        throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).");
                    }
                }
    
                var handler = await Handlers.GetHandlerAsync(context, scheme);
                if (handler == null)
                {
                    throw await CreateMissingHandlerException(scheme);
                }
    
                await handler.ChallengeAsync(properties);
            }
    
            /// <summary>
            /// Forbid the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            public virtual async Task ForbidAsync(HttpContext context, string? scheme, AuthenticationProperties? properties)
            {
                if (scheme == null)
                {
                    var defaultForbidScheme = await Schemes.GetDefaultForbidSchemeAsync();
                    scheme = defaultForbidScheme?.Name;
                    if (scheme == null)
                    {
                        throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultForbidScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).");
                    }
                }
    
                var handler = await Handlers.GetHandlerAsync(context, scheme);
                if (handler == null)
                {
                    throw await CreateMissingHandlerException(scheme);
                }
    
                await handler.ForbidAsync(properties);
            }
    
            /// <summary>
            /// Sign a principal in for the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="principal">The <see cref="ClaimsPrincipal"/> to sign in.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            public virtual async Task SignInAsync(HttpContext context, string? scheme, ClaimsPrincipal principal, AuthenticationProperties? properties)
            {
                if (principal == null)
                {
                    throw new ArgumentNullException(nameof(principal));
                }
    
                if (Options.RequireAuthenticatedSignIn)
                {
                    if (principal.Identity == null)
                    {
                        throw new InvalidOperationException("SignInAsync when principal.Identity == null is not allowed when AuthenticationOptions.RequireAuthenticatedSignIn is true.");
                    }
                    if (!principal.Identity.IsAuthenticated)
                    {
                        throw new InvalidOperationException("SignInAsync when principal.Identity.IsAuthenticated is false is not allowed when AuthenticationOptions.RequireAuthenticatedSignIn is true.");
                    }
                }
    
                if (scheme == null)
                {
                    var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync();
                    scheme = defaultScheme?.Name;
                    if (scheme == null)
                    {
                        throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignInScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).");
                    }
                }
    
                var handler = await Handlers.GetHandlerAsync(context, scheme);
                if (handler == null)
                {
                    throw await CreateMissingSignInHandlerException(scheme);
                }
    
                var signInHandler = handler as IAuthenticationSignInHandler;
                if (signInHandler == null)
                {
                    throw await CreateMismatchedSignInHandlerException(scheme, handler);
                }
    
                await signInHandler.SignInAsync(principal, properties);
            }
    
            /// <summary>
            /// Sign out the specified authentication scheme.
            /// </summary>
            /// <param name="context">The <see cref="HttpContext"/>.</param>
            /// <param name="scheme">The name of the authentication scheme.</param>
            /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
            /// <returns>A task.</returns>
            public virtual async Task SignOutAsync(HttpContext context, string? scheme, AuthenticationProperties? properties)
            {
                if (scheme == null)
                {
                    var defaultScheme = await Schemes.GetDefaultSignOutSchemeAsync();
                    scheme = defaultScheme?.Name;
                    if (scheme == null)
                    {
                        throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignOutScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).");
                    }
                }
    
                var handler = await Handlers.GetHandlerAsync(context, scheme);
                if (handler == null)
                {
                    throw await CreateMissingSignOutHandlerException(scheme);
                }
    
                var signOutHandler = handler as IAuthenticationSignOutHandler;
                if (signOutHandler == null)
                {
                    throw await CreateMismatchedSignOutHandlerException(scheme, handler);
                }
    
                await signOutHandler.SignOutAsync(properties);
            }
    
            private async Task<Exception> CreateMissingHandlerException(string scheme)
            {
                var schemes = string.Join(", ", (await Schemes.GetAllSchemesAsync()).Select(sch => sch.Name));
    
                var footer = $" Did you forget to call AddAuthentication().Add[SomeAuthHandler](\"{scheme}\",...)?";
    
                if (string.IsNullOrEmpty(schemes))
                {
                    return new InvalidOperationException(
                        $"No authentication handlers are registered." + footer);
                }
    
                return new InvalidOperationException(
                    $"No authentication handler is registered for the scheme '{scheme}'. The registered schemes are: {schemes}." + footer);
            }
    
            private async Task<string> GetAllSignInSchemeNames()
            {
                return string.Join(", ", (await Schemes.GetAllSchemesAsync())
                    .Where(sch => typeof(IAuthenticationSignInHandler).IsAssignableFrom(sch.HandlerType))
                    .Select(sch => sch.Name));
            }
    
            private async Task<Exception> CreateMissingSignInHandlerException(string scheme)
            {
                var schemes = await GetAllSignInSchemeNames();
    
                // CookieAuth is the only implementation of sign-in.
                var footer = $" Did you forget to call AddAuthentication().AddCookie(\"{scheme}\",...)?";
    
                if (string.IsNullOrEmpty(schemes))
                {
                    return new InvalidOperationException(
                        $"No sign-in authentication handlers are registered." + footer);
                }
    
                return new InvalidOperationException(
                    $"No sign-in authentication handler is registered for the scheme '{scheme}'. The registered sign-in schemes are: {schemes}." + footer);
            }
    
            private async Task<Exception> CreateMismatchedSignInHandlerException(string scheme, IAuthenticationHandler handler)
            {
                var schemes = await GetAllSignInSchemeNames();
    
                var mismatchError = $"The authentication handler registered for scheme '{scheme}' is '{handler.GetType().Name}' which cannot be used for SignInAsync. ";
    
                if (string.IsNullOrEmpty(schemes))
                {
                    // CookieAuth is the only implementation of sign-in.
                    return new InvalidOperationException(mismatchError
                        + $"Did you forget to call AddAuthentication().AddCookie(\"Cookies\") and SignInAsync(\"Cookies\",...)?");
                }
    
                return new InvalidOperationException(mismatchError + $"The registered sign-in schemes are: {schemes}.");
            }
    
            private async Task<string> GetAllSignOutSchemeNames()
            {
                return string.Join(", ", (await Schemes.GetAllSchemesAsync())
                    .Where(sch => typeof(IAuthenticationSignOutHandler).IsAssignableFrom(sch.HandlerType))
                    .Select(sch => sch.Name));
            }
    
            private async Task<Exception> CreateMissingSignOutHandlerException(string scheme)
            {
                var schemes = await GetAllSignOutSchemeNames();
    
                var footer = $" Did you forget to call AddAuthentication().AddCookie(\"{scheme}\",...)?";
    
                if (string.IsNullOrEmpty(schemes))
                {
                    // CookieAuth is the most common implementation of sign-out, but OpenIdConnect and WsFederation also support it.
                    return new InvalidOperationException($"No sign-out authentication handlers are registered." + footer);
                }
    
                return new InvalidOperationException(
                    $"No sign-out authentication handler is registered for the scheme '{scheme}'. The registered sign-out schemes are: {schemes}." + footer);
            }
    
            private async Task<Exception> CreateMismatchedSignOutHandlerException(string scheme, IAuthenticationHandler handler)
            {
                var schemes = await GetAllSignOutSchemeNames();
    
                var mismatchError = $"The authentication handler registered for scheme '{scheme}' is '{handler.GetType().Name}' which cannot be used for {nameof(SignOutAsync)}. ";
    
                if (string.IsNullOrEmpty(schemes))
                {
                    // CookieAuth is the most common implementation of sign-out, but OpenIdConnect and WsFederation also support it.
                    return new InvalidOperationException(mismatchError
                        + $"Did you forget to call AddAuthentication().AddCookie(\"Cookies\") and {nameof(SignOutAsync)}(\"Cookies\",...)?");
                }
    
                return new InvalidOperationException(mismatchError + $"The registered sign-out schemes are: {schemes}.");
            }
        }
    }
  • 相关阅读:
    day25:接口类和抽象类
    vue1
    How the weather influences your mood?
    机器学习实验方法与原理
    How human activities damage the environment
    Slow food
    Brief Introduction to Esports
    Massive open online course (MOOC)
    Online learning in higher education
    Tensorflow Dataset API
  • 原文地址:https://www.cnblogs.com/htlp/p/15255818.html
Copyright © 2011-2022 走看看