当用户在 Blazor Webassembly 身份验证和授权中具有多个角色时出现问题?
Posted
技术标签:
【中文标题】当用户在 Blazor Webassembly 身份验证和授权中具有多个角色时出现问题?【英文标题】:Problem when user has multi roles in Blazor Webassembly authentication and authorisation? 【发布时间】:2021-10-23 21:28:32 【问题描述】:我有一个 Blazor Webassembly 解决方案,当我使用用户(具有多个角色)登录时,登录操作显示错误:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentException: An item with the same key has already been added. Key: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
at REMO.Server.Controllers.AuthController.CurrentUserInfo() in D:\REMO\REMO\Server\Controllers\AuthController.cs:line 87
at lambda_method29(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean&
isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
按照我的自定义身份验证提供程序:
public class CustomStateProvider : AuthenticationStateProvider
private readonly IAuthService api;
private CurrentUser _currentUser;
public CustomStateProvider(IAuthService api)
this.api = api;
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
var identity = new ClaimsIdentity();
try
var userInfo = await GetCurrentUser();
var roleClaims = identity.FindAll(identity.RoleClaimType);
if (userInfo.IsAuthenticated)
var claims = new[]
new Claim(ClaimTypes.Name, _currentUser.UserName)
.Concat(_currentUser.Claims.Select(c => new Claim(c.Key, c.Value)));
identity = new ClaimsIdentity(claims, "Server authentication");
catch (HttpRequestException ex)
Console.WriteLine("Request failed:" + ex.ToString());
return new AuthenticationState(new ClaimsPrincipal(identity));
Startup.cs
...
services.AddDbContext<ApplicationDBContext>(options => options .UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDBContext>();
...
问题似乎是一个身份存在多个角色。 如果身份只有一个角色,则不会出现问题。
【问题讨论】:
如果您已经拥有同名声明,请登录登录 想你,...如果我用一个用户登录没有问题!... 您好,zekad,如果答案解决了您的问题,请将其标记为正确答案,以便对未来的用户有所帮助。 嗨 Nicola,非常感谢您的回答,您的回答是正确且合乎逻辑的,但我现在无法设置正确的代码...... 【参考方案1】:您的问题是 role 声明密钥的构造。 这个键,如果是多个角色,必须是一个数组。 您的 JWT 令牌中不能有多个“角色”键。
我认为您已经使用了 Mukesh 中的代码并且是一个很好的起点,但是如果您阅读评论,最后一个解释了像您这样的问题。
所以你需要修改该行
.Concat(_currentUser.Claims.Select(c => new Claim(c.Key, c.Value)));
通过 LINQ 提取所有 不 类型为 role 的声明,并将它们添加到 claims
数组中。
现在您需要创建一个包含所有 role 类型声明的数组(我认为它们来自您的 API)并添加一个数组类型的单个 role 声明条目。
修改后我认为它应该可以工作。
解码后的 JWT 令牌应具有以下形式:
"sub": "nbiada",
"jti": "123...",
"role" : [
"User",
"Admin"
],
"exp": 12345467,
...
注意:
我已经缩短了role
键,在你的实现中应该是http://schemas.microsoft.com/ws/2008/06/identity/claims/role
【讨论】:
以上是关于当用户在 Blazor Webassembly 身份验证和授权中具有多个角色时出现问题?的主要内容,如果未能解决你的问题,请参考以下文章
Blazor WebAssembly - 用户帐户和身份服务器的最佳实践
在 Blazor WebAssembly 中获取第三方登录的用户数据
如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?
Blazor WebAssembly 与身份服务器通过表单传递用户名