openid什么意思_openId

openid什么意思_openId在使用IdentityServer作IdentityProvider的时候,我们在NetCore的ConfigureServices((IServiceCollectionservices))方

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

  在使用Identity Server作Identity Provider的时候,我们在NetCore的ConfigureServices((IServiceCollection services))方法中,常需要指定options的Authority,如下代码所示:

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
          
            //
            #region MVC client
            //关闭了 JWT 身份信息类型映射
            //这样就允许 well-known 身份信息(比如,“sub” 和 “idp”)无干扰地流过。
            //这个身份信息类型映射的“清理”必须在调用 AddAuthentication()之前完成
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
               .AddCookie("Cookies")

              .AddOpenIdConnect("oidc", options =>
              {
                
                  options.Authority = "http://localhost:5001";
                  options.RequireHttpsMetadata = false;
                  options.ClientId = "code_client";
                  //Client secret
                  options.ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A".ToString();
                  //code方式
                  options.ResponseType = "code";
                  //Scope可以理解为申请何种操作范围
                  options.Scope.Add("code_scope1"); //添加授权资源
   
                  options.SaveTokens = true;
                  options.GetClaimsFromUserInfoEndpoint = true;
                
              });

            #endregion
            services.ConfigureNonBreakingSameSiteCookies();
        }

  其中options.Authority = “http://localhost:5001″需要设置,如果把它注释掉,则会报如下的错误,从这个异常看得出来,应该是Authority没有设置:

 openid什么意思_openId

   那么为什么我们一定要设置.Authority 呢?我们一步一步来看看:

  1.在调用services.AddOpenIdConnect方法时,实质调用的是OpenIdConnectExtensions静态类的AddOpenIdConnect静态方法,如下所示:

 public static AuthenticationBuilder AddOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<OpenIdConnectOptions> configureOptions)
        {
            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIdConnectOptions>, OpenIdConnectPostConfigureOptions>());
            return builder.AddRemoteScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, displayName, configureOptions);
        }

 2.从上面的代码看得出,实际上调用的是AuthenticationBuilder的AddRemoteScheme扩展方法,如下所示:

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


 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 =>
            {
                //注册Scheme对应的HandlerType
                o.AddScheme(authenticationScheme, scheme => {
                    scheme.HandlerType = typeof(THandler);
                    scheme.DisplayName = displayName;
                });
            });
            if (configureOptions != null)
            {
                Services.Configure(authenticationScheme, configureOptions);
            }
            //Options验证
            Services.AddOptions<TOptions>(authenticationScheme).Validate(o => {
                o.Validate(authenticationScheme);
                return true;
            });
            Services.AddTransient<THandler>();
            return this;
        }

  

  看得出来,实际上调用的是AddSchemeHelper方法,在这个方法里,有一个很重要的Options验证:

 Services.AddOptions<TOptions>(authenticationScheme).Validate(o => {
                o.Validate(authenticationScheme);
                return true;
            });

在这里需要对AuthenticationSchemeOptions进行验证

   3.上一步的Options验证中实际上调用的是OpenIdConnectOptions类的Validate方法,如下所示:

 /// <summary>
        /// Check that the options are valid.  Should throw an exception if things are not ok.
        /// </summary>
        public override void Validate()
        {
            base.Validate();

            if (MaxAge.HasValue && MaxAge.Value < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(MaxAge), MaxAge.Value, "The value must not be a negative TimeSpan.");
            }

            if (string.IsNullOrEmpty(ClientId))
            {
                throw new ArgumentException("Options.ClientId must be provided", nameof(ClientId));
            }

            if (!CallbackPath.HasValue)
            {
                throw new ArgumentException("Options.CallbackPath must be provided.", nameof(CallbackPath));
            }

            //如果Authority没有设置,则报下面这个异常
            if (ConfigurationManager == null)
            {
                throw new InvalidOperationException($"Provide {nameof(Authority)}, {nameof(MetadataAddress)}, "
                + $"{nameof(Configuration)}, or {nameof(ConfigurationManager)} to {nameof(OpenIdConnectOptions)}");
            }
        }

  从这里看得出来,如果ConfigurationManager为空,则就会报前面中的异常了,所以异常就是这么来的。

 

4.那么为什么ConfigurationManager为空呢?我们回顾OpenIdConnectExtensions的AddOpenIdConnect方法:

   public static AuthenticationBuilder AddOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<OpenIdConnectOptions> configureOptions)
        {
            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIdConnectOptions>, OpenIdConnectPostConfigureOptions>());
            return builder.AddRemoteScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, displayName, configureOptions);
        }  

看得出AuthenticationBuilder的Services添加了一个名为OpenIdConnectPostConfigureOptions的单例服务: builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIdConnectOptions>, OpenIdConnectPostConfigureOptions>());

继续看下OpenIdConnectPostConfigureOptions的源码:

      /// <summary>
        /// Invoked to post configure a TOptions instance.
        /// </summary>
        /// <param name="name">The name of the options instance being configured.</param>
        /// <param name="options">The options instance to configure.</param>
        public void PostConfigure(string name, OpenIdConnectOptions options)
        {
            options.DataProtectionProvider = options.DataProtectionProvider ?? _dp;

            if (string.IsNullOrEmpty(options.SignOutScheme))
            {
                options.SignOutScheme = options.SignInScheme;
            }

            if (options.StateDataFormat == null)
            {
                var dataProtector = options.DataProtectionProvider.CreateProtector(
                    typeof(OpenIdConnectHandler).FullName!, name, "v1");
                options.StateDataFormat = new PropertiesDataFormat(dataProtector);
            }

            if (options.StringDataFormat == null)
            {
                var dataProtector = options.DataProtectionProvider.CreateProtector(
                    typeof(OpenIdConnectHandler).FullName!,
                    typeof(string).FullName!,
                    name,
                    "v1");

                options.StringDataFormat = new SecureDataFormat<string>(new StringSerializer(), dataProtector);
            }

            if (string.IsNullOrEmpty(options.TokenValidationParameters.ValidAudience) && !string.IsNullOrEmpty(options.ClientId))
            {
                options.TokenValidationParameters.ValidAudience = options.ClientId;
            }

            if (options.Backchannel == null)
            {
                options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler());
                options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OpenIdConnect handler");
                options.Backchannel.Timeout = options.BackchannelTimeout;
                options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
            }

            if (options.ConfigurationManager == null)
            {
                if (options.Configuration != null)
                {
                    options.ConfigurationManager = new StaticConfigurationManager<OpenIdConnectConfiguration>(options.Configuration);
                }
                else if (!(string.IsNullOrEmpty(options.MetadataAddress) && string.IsNullOrEmpty(options.Authority)))
                {
                    if (string.IsNullOrEmpty(options.MetadataAddress) && !string.IsNullOrEmpty(options.Authority))
                    {
                        options.MetadataAddress = options.Authority;
                        if (!options.MetadataAddress.EndsWith("/", StringComparison.Ordinal))
                        {
                            options.MetadataAddress += "/";
                        }

                        options.MetadataAddress += ".well-known/openid-configuration";
                    }

                    if (options.RequireHttpsMetadata && !(options.MetadataAddress?.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ?? false))
                    {
                        throw new InvalidOperationException("The MetadataAddress or Authority must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false.");
                    }

                    options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.MetadataAddress, new OpenIdConnectConfigurationRetriever(),
                        new HttpDocumentRetriever(options.Backchannel) { RequireHttps = options.RequireHttpsMetadata })
                    {
                        RefreshInterval = options.RefreshInterval,
                        AutomaticRefreshInterval = options.AutomaticRefreshInterval,
                    };
                }
            }
        }

  

注意看两个if语句,才发现OpenIdConnectOptions的Authority和MetadataAddress在都没有设置的情况下,OpenIdConnectOptions的ConfigurationManager为空!

 

    所以,从上文看得出,如果不设置OpenIdConnectOptions的Authority,那么无法进行OpenIdConnect认证哦!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170756.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • php隐式转换,隐式转换如何使用?总结隐式转换实例用法「建议收藏」

    php隐式转换,隐式转换如何使用?总结隐式转换实例用法「建议收藏」JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object。object是引用类型,其它的五种是基本类型或者是原始类型。我们可以用typeof方法打印来某个是属于哪个类型的。不同类型的变量比较要先转类型,叫做类型转换,类型转换也叫隐式转换。隐式转换通常发生在运算符加减乘除,等于,还有小于,大于等。。typeof’11’…

    2022年10月11日
    2
  • 大数据分析-用户画像详解

    转自:百丽百灵(ID:BL100BL)转自数据分析公号,来源:数据客什么是用户画像?用户画像(UserProfile),作为大数据的根基,它完美地抽象出一个用户的信息全貌,为进一步精准、快速地分析用户行为习惯、消费习惯等重要信息,提供了足够的数据基础,奠定了大数据时代的基石。用户画像,即用户信息标签化,就是企业通过收集与分

    2022年4月6日
    32
  • 编程xml速度最快的语言_xml语言是什么的缩写

    编程xml速度最快的语言_xml语言是什么的缩写国际化多语言转换工具方案介绍当项目涉及到多语言国际化的时候,我们需要把string.xml翻译成其他国家语言,一般翻译公司会需要excel等格式文档,可是这翻译文件实在是不好整,幸好有大神做了个py工具实现string文件转excel.目前有两种方式:Localizable.strings2Excel(下载源码,然后在终端输入命令跑脚本进行文件转换)作者:CatchZeng,https://github.com/CatchZeng/Localizable.strings2ExcelL

    2022年8月22日
    11
  • Spring Boot2.0迁移概括

    Spring Boot2.0迁移概括首先,SpringBoot2.0需要Java8或更高版本。不再支持Java6和7了。在SpringBoot2.0中,许多配置属性被重新命名/删除,开发人员需要更新application.properties/application.yml相应的配置。为了帮助你解决这一问题,SpringBoot发布了一个新spring-boot-properties-migr…

    2022年5月27日
    66
  • 三种JS截取字符串方法

    三种JS截取字符串方法转载: https://www.cnblogs.com/zccfun/p/6054533.htmlJS提供三个截取字符串的方法,分别是:slice(),substring()和substr(),它们都可以接受一个或两个参数:varstmp="rcinn.cn";使用一个参数alert(stmp.slice(3));//从第4个字符开始,截取到最后个字符;返回"nn.cn"a…

    2022年4月29日
    53
  • 思科 计算机网络 期末考试答案

    思科 计算机网络 期末考试答案1.以下哪个域名是顶级域的一个示例?A.root.cisco.comB.www.cisco.comC.cisco.comD…com2.第2层数据封装有哪三个主要功能?(请选择三项。)A.将位组定界为帧B.通过冲突检测方法纠正错误C.在介质中放置和删除帧D.将位转换为数据信号E.通过CRC计算检测错误F.数据链路层寻址G.使用端口号控制会话3.管理员在发出ping命令之后在交换机上使用Ctrl-Shift-6键组合。使用这些按键有什么用途?A.允许用户完成命令B.中

    2022年7月23日
    15

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号