OAuthHandler

OAuthHandler

aspnetcore/src/Security/Authentication/MicrosoftAccount/src/MicrosoftAccountHandler.cs at main · dotnet/aspnetcore (github.com)

aspnetcore/src/Security/Authentication/MicrosoftAccount/src/MicrosoftAccountDefaults.cs at main · dotnet/aspnetcore (github.com)

 

 

AspNet.Security.OAuth.Providers/src/AspNet.Security.OAuth.Alipay/AlipayAuthenticationHandler.cs at dev · aspnet-contrib/AspNet.Security.OAuth.Providers (github.com)

AspNet.Security.OAuth.Providers/src/AspNet.Security.OAuth.Alipay/AlipayAuthenticationOptions.cs at dev · aspnet-contrib/AspNet.Security.OAuth.Providers (github.com)

 

AspNet.Security.OAuth.Providers/src/AspNet.Security.OAuth.Baidu/BaiduAuthenticationHandler.cs at dev · aspnet-contrib/AspNet.Security.OAuth.Providers (github.com)

AspNet.Security.OAuth.Providers/src/AspNet.Security.OAuth.Baidu/BaiduAuthenticationOptions.cs at dev · aspnet-contrib/AspNet.Security.OAuth.Providers (github.com)

 

每个handler都需要继承aspnetcore/src/Security/Authentication/OAuth/src/OAuthHandler.cs at main · dotnet/aspnetcore (github.com)

每个都是扩展AuthenticationBuilder,给他添加新的方法,把对应的handler传递过去

 public static AuthenticationBuilder AddAlipay(
        [NotNull] this AuthenticationBuilder builder,
        [NotNull] string scheme,
        [CanBeNull] string caption,
        [NotNull] Action<AlipayAuthenticationOptions> configuration)
    {
        return builder.AddOAuth<AlipayAuthenticationOptions, AlipayAuthenticationHandler>(scheme, caption, configuration);
    }

public static AuthenticationBuilder AddBaidu(
        [NotNull] this AuthenticationBuilder builder,
        [NotNull] string scheme,
        [CanBeNull] string caption,
        [NotNull] Action<BaiduAuthenticationOptions> configuration)
    {
        return builder.AddOAuth<BaiduAuthenticationOptions, BaiduAuthenticationHandler>(scheme, caption, configuration);
    }

添加Authentication的时候,最后都是调用builder.AddOAuth,需要实现自己的AuthenticationOptions和AuthenticationHandler

 

builder的AddOAuth本身也是通过给AuthenticationBuilder添加扩展方法实现的

aspnetcore/src/Security/Authentication/OAuth/src/OAuthExtensions.cs at main · dotnet/aspnetcore (github.com)


    /// <summary>
    /// Adds OAuth 2.0 based authentication to <see cref="AuthenticationBuilder"/> using the specified authentication scheme.
    /// </summary>
    /// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
    /// <param name="authenticationScheme">The authentication scheme.</param>
    /// <param name="configureOptions">A delegate to configure <see cref="OAuthOptions"/>.</param>
    /// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
    public static AuthenticationBuilder AddOAuth(this AuthenticationBuilder builder, string authenticationScheme, Action<OAuthOptions> configureOptions)
        => builder.AddOAuth<OAuthOptions, OAuthHandler<OAuthOptions>>(authenticationScheme, configureOptions);

    /// <summary>
    /// Adds OAuth 2.0 based authentication to <see cref="AuthenticationBuilder"/> using the specified authentication scheme.
    /// </summary>
    /// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
    /// <param name="authenticationScheme">The authentication scheme.</param>
    /// <param name="displayName">A display name for the authentication handler.</param>
    /// <param name="configureOptions">A delegate to configure <see cref="OAuthOptions"/>.</param>
    /// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
    public static AuthenticationBuilder AddOAuth(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<OAuthOptions> configureOptions)
        => builder.AddOAuth<OAuthOptions, OAuthHandler<OAuthOptions>>(authenticationScheme, displayName, configureOptions);

    /// <summary>
    /// Adds OAuth 2.0 based authentication to <see cref="AuthenticationBuilder"/> using the specified authentication scheme.
    /// </summary>
    /// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
    /// <param name="authenticationScheme">The authentication scheme.</param>
    /// <param name="configureOptions">A delegate to configure the handler specific options.</param>
    /// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
    public static AuthenticationBuilder AddOAuth<TOptions, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THandler>(this AuthenticationBuilder builder, string authenticationScheme, Action<TOptions> configureOptions)
        where TOptions : OAuthOptions, new()
        where THandler : OAuthHandler<TOptions>
        => builder.AddOAuth<TOptions, THandler>(authenticationScheme, OAuthDefaults.DisplayName, configureOptions);

    /// <summary>
    /// Adds OAuth 2.0 based authentication to <see cref="AuthenticationBuilder"/> using the specified authentication scheme.
    /// </summary>
    /// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
    /// <param name="authenticationScheme">The authentication scheme.</param>
    /// <param name="displayName">A display name for the authentication handler.</param>
    /// <param name="configureOptions">A delegate to configure the handler specific options.</param>
    /// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
    public static AuthenticationBuilder AddOAuth<TOptions, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THandler>(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<TOptions> configureOptions)
        where TOptions : OAuthOptions, new()
        where THandler : OAuthHandler<TOptions>
    {
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TOptions>, OAuthPostConfigureOptions<TOptions, THandler>>());
        return builder.AddRemoteScheme<TOptions, THandler>(authenticationScheme, displayName, configureOptions);
    }

一层一层的封装下来,最终调用的是 AddRemoteScheme

 

微软官方的测试demo

aspnetcore/src/Identity/testassets/Identity.DefaultUI.WebSite/Services/ContosoAuthenticationHandler.cs at main · dotnet/aspnetcore (github.com)

 

aspnetcore/src/Identity/Core/src/IdentityAuthenticationBuilderExtensions.cs at main · dotnet/aspnetcore (github.com)

aspnetcore/src/Identity/Core/src/IdentityCookiesBuilderExtensions.cs at main · dotnet/aspnetcore (github.com)

 

AddRemoteScheme的源码

aspnetcore/src/Security/Authentication/Core/src/AuthenticationBuilder.cs at main · dotnet/aspnetcore (github.com)

/// <summary>
    /// The services being configured.
    /// </summary>
    public virtual IServiceCollection Services { get; }

    private AuthenticationBuilder AddSchemeHelper<TOptions, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THandler>(string authenticationScheme, string? displayName, Action<TOptions>? configureOptions)
        where TOptions : AuthenticationSchemeOptions, new()
        where THandler : class, IAuthenticationHandler
    {
        Services.Configure<AuthenticationOptions>(o =>
        {
            o.AddScheme(authenticationScheme, scheme =>
            {
                scheme.HandlerType = typeof(THandler);
                scheme.DisplayName = displayName;
            });
        });
        if (configureOptions != null)
        {
            Services.Configure(authenticationScheme, configureOptions);
        }
        Services.AddOptions<TOptions>(authenticationScheme).Validate(o =>
        {
            o.Validate(authenticationScheme);
            return true;
        });
        Services.AddTransient<THandler>();
        Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TOptions>, PostConfigureAuthenticationSchemeOptions<TOptions>>());
        return this;
    }

    /// <summary>
    /// Adds a <see cref="AuthenticationScheme"/> which can be used by <see cref="IAuthenticationService"/>.
    /// </summary>
    /// <typeparam name="TOptions">The <see cref="AuthenticationSchemeOptions"/> type to configure the handler.</typeparam>
    /// <typeparam name="THandler">The <see cref="AuthenticationHandler{TOptions}"/> used to handle this scheme.</typeparam>
    /// <param name="authenticationScheme">The name of this scheme.</param>
    /// <param name="displayName">The display name of this scheme.</param>
    /// <param name="configureOptions">Used to configure the scheme options.</param>
    /// <returns>The builder.</returns>
    public virtual AuthenticationBuilder AddScheme<TOptions, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THandler>(string authenticationScheme, string? displayName, Action<TOptions>? configureOptions)
        where TOptions : AuthenticationSchemeOptions, new()
        where THandler : AuthenticationHandler<TOptions>
        => AddSchemeHelper<TOptions, THandler>(authenticationScheme, displayName, configureOptions);

    /// <summary>
    /// Adds a <see cref="RemoteAuthenticationHandler{TOptions}"/> based <see cref="AuthenticationScheme"/> that supports remote authentication
    /// which can be used by <see cref="IAuthenticationService"/>.
    /// </summary>
    /// <typeparam name="TOptions">The <see cref="RemoteAuthenticationOptions"/> type to configure the handler.</typeparam>
    /// <typeparam name="THandler">The <see cref="RemoteAuthenticationHandler{TOptions}"/> used to handle this scheme.</typeparam>
    /// <param name="authenticationScheme">The name of this scheme.</param>
    /// <param name="displayName">The display name of this scheme.</param>
    /// <param name="configureOptions">Used to configure the scheme options.</param>
    /// <returns>The builder.</returns>
    public virtual AuthenticationBuilder AddRemoteScheme<TOptions, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THandler>(string authenticationScheme, string? displayName, Action<TOptions>? configureOptions)
        where TOptions : RemoteAuthenticationOptions, new()
        where THandler : RemoteAuthenticationHandler<TOptions>
    {
        Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TOptions>, EnsureSignInScheme<TOptions>>());
        return AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureOptions: configureOptions);
    }

最后是通过Services.Configure<AuthenticationOptions>(o =>
        {
            o.AddScheme(authenticationScheme, scheme =>
            {
                scheme.HandlerType = typeof(THandler);
                scheme.DisplayName = displayName;
            });
        });

把scheme加进去的

 

 

[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.Options")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]

https://github.com/dotnet/runtime/blob/4822e3c3aa77eb82b2fb33c9321f923cf11ddde6/src/libraries/Microsoft.Extensions.Options/src/OptionsServiceCollectionExtensions.cs#L45


        /// <summary>
        /// Registers an action used to configure a particular type of options.
        /// Note: These are run before all <seealso cref="PostConfigure{TOptions}(IServiceCollection, Action{TOptions})"/>.
        /// </summary>
        /// <typeparam name="TOptions">The options type to be configured.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
        /// <param name="configureOptions">The action used to configure the options.</param>
        /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
        public static IServiceCollection Configure<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
            => services.Configure(Options.Options.DefaultName, configureOptions);

        /// <summary>
        /// Registers an action used to configure a particular type of options.
        /// Note: These are run before all <seealso cref="PostConfigure{TOptions}(IServiceCollection, Action{TOptions})"/>.
        /// </summary>
        /// <typeparam name="TOptions">The options type to be configured.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
        /// <param name="name">The name of the options instance.</param>
        /// <param name="configureOptions">The action used to configure the options.</param>
        /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
        public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions)
            where TOptions : class
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (configureOptions == null)
            {
                throw new ArgumentNullException(nameof(configureOptions));
            }

            services.AddOptions();
            services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, configureOptions));
            return services;
        }

 

posted @ 2023-07-20 10:37  ChuckLu  阅读(25)  评论(0编辑  收藏  举报