使用 .mapuniquejsonkey 时,@context.user.identity.name 为空
Posted
技术标签:
【中文标题】使用 .mapuniquejsonkey 时,@context.user.identity.name 为空【英文标题】:@context.user.identity.name is null when using .mapuniquejsonkey 【发布时间】:2021-09-18 02:59:53 【问题描述】:我有两个应用程序,Blazor 和 IdentityServer。我注意到在ConfigureServices method
options.ClaimActions.MapUniqueJsonKey("role","role")
下的Startup.cs
文件和使用@context.user.identity.name
的index.razor
文件内部它返回null。但是当我评论 claimactions
时,将其替换为以下内容:
options.TokenValidationParameters = new TokenValidationParameters
NameClaimType = "name"
;
options.UseTokenLifetime = false;
它将返回当前用户的电子邮件。 当我用上面的代码替换 claimactions.mapuniquejsonkey
行时它只返回一个值有什么原因吗?我试图理解为什么会这样。我在有关 TokenValidationParameters 的文档中看到了,但仍然没有像我想的那样理解它。
当我有 options.ClaimActions.MapUniqueJsonKey("role","role")
行时,它返回 null:
当我注释掉该行并将其替换为上面的这两行时:
如果您想查看完整代码,请参阅以下内容:
Startup.cs
:
public void ConfigureServices(IServiceCollection services)
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton(sp => new HttpClient BaseAddress = new Uri("http://localhost:36626") ); // WebApi project
services.AddTransient<IWeatherForecastServices, WeatherForecastServices>();
services.AddAuthentication(options =>
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.SignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.Authority = "https://localhost:5443"; // IdentityServer Project
options.ClientId = "interactive";
options.ClientSecret = "KEY";
options.ResponseType = "code";
options.Scope.Add("profile"); // default scope
options.Scope.Add("scope2");
options.Scope.Add("roles");
options.Scope.Add("permissions");
options.Scope.Add("email");
options.ClaimActions.MapUniqueJsonKey("role", "role");
/* options.TokenValidationParameters = new TokenValidationParameters
NameClaimType = "name"
;
options.UseTokenLifetime = false; */
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
);
services.AddScoped<TokenProvider>();
services.AddCors(options =>
options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader());
);
services.AddAuthorization(options =>
options.AddPolicy(Policy.Policies.IsUser,
Policy.Policies.IsUserPolicy());
);
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("Open");
app.UseEndpoints(endpoints =>
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
);
Index.razor
:
Index.razor
<AuthorizeView Policy="@Policy.Policies.IsUser">
<h3>Welcome, <b>@context.User.Identity.Name</b></h3>
<p>You can only see this if you satisfy the IsUser policy.</p>
</AuthorizeView>
来自 IdentityServer 的Config.cs
:
.......
new Client
ClientId = "interactive",
ClientSecrets = new Secret("KEY".Sha256()) ,
RequirePkce = true,
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = "https://localhost:5445/signin-oidc", "https://localhost:44327/signin-oidc" ,
FrontChannelLogoutUri = "https://localhost:5445/signout-oidc",
PostLogoutRedirectUris = "https://localhost:5445/signout-callback-oidc" ,
AlwaysIncludeUserClaimsInIdToken = true,
AllowOfflineAccess = true,
AllowedScopes = "openid", "profile", "email" , "scope2" ,"weatherforecast-api","roles","permissions"
,
;
【问题讨论】:
【参考方案1】:名称声明和角色声明映射到 ASP.NET Core HTTP 上下文中的默认属性。有时需要对默认属性使用不同的声明,或者名称声明和角色声明与默认值不匹配。声明可以使用 TokenValidationParameters 属性进行映射,并根据需要设置为任何声明。
以下代码 sn -p 说明了 TokenValidationParameters 的使用:
options.TokenValidationParameters = new TokenValidationParameters
NameClaimType = "email",
RoleClaimType = "role"
;
如您所见,名称声明映射到“电子邮件”字段,但通常它会映射到“姓名”字段。
注意:由于您的设置请求配置文件范围 (options.Scope.Add("profile");
),因此不需要额外的声明映射。也就是说NameClaimType = "name"
是多余的。
获取用户声明的另一种方法是使用 OpenID Connect 用户信息 API。 ASP.NET Core 客户端应用程序使用 GetClaimsFromUserInfoEndpoint 属性来配置它。与第一个设置的一个重要区别是,您必须使用 MapUniqueJsonKey 方法指定所需的声明,否则客户端应用程序中将只有 name、given_name 和 email 标准声明可用。 id_token 中包含的声明是默认映射的。这是与第一个选项的主要区别。您必须明确定义您需要的一些声明:
// YOU MUST HAVE THE FIRST LINE WITHOUT WHICH YOU'LL GET NULL VALUES
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapUniqueJsonKey("preferred_username",
"preferred_username");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
options.ClaimActions.MapUniqueJsonKey("role","role");
注意:您应该从我和 Brian Parker 那里寻找与身份验证和授权相关的答案。我们已经回答了 WebAssembly 和 Blazor 服务器应用程序中的许多问题。这些不是关于该主题的文章,而是我们提供给开发人员的解决方案,它们涵盖了该主题的许多方面,包括自定义声明、声明转换等。Brian Parker 在 Github 中也有完整的应用程序...查看。
【讨论】:
以上是关于使用 .mapuniquejsonkey 时,@context.user.identity.name 为空的主要内容,如果未能解决你的问题,请参考以下文章
我正在使用 Enterprise Architect,在 C/C++ 中进行逆向工程时遇到了一些问题