How do I persist multiple ClaimTypes.Role values in User's Claims list?
我正在构建一个 ASP.NET Core (v3.1) 模块,并且我刚刚设法配置了一个 OpenIdConnect 身份验证。现在,我需要从 API 获取所有用户的角色,以便授予或拒绝对它们的访问权限,然后我通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | OnAuthorizationCodeReceived = async (context) => { // Uses the authentication code and gets the access and refresh token var client = new HttpClient(); var response = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest() { Address = urlServer +"/connect/token", ClientId ="hybrid", Code = context.TokenEndpointRequest.Code, RedirectUri = context.TokenEndpointRequest.RedirectUri, } if (response.IsError) throw new Exception(response.Error); var identity = new ClaimsIdentity(context.Principal.Identity); var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API listRoles.ForEach(role => identity.AddClaim(new Claim(ClaimTypes.Role, role))); context.HttpContext.User = new ClaimsPrincipal(identity); context.HandleCodeRedemption(response.AccessToken, response.IdentityToken); } |
在调试时,我注意到所有角色都添加到此行之后的用户声明列表中:
1 |
但是,显然,在我的 Home 控制器中(这是用户在经过身份验证后被重定向到的地方),当我访问 HttpContext.User 时,我似乎找不到我之前添加的任何角色,除了" Admin"(我猜是默认的 ClaimTypes.Role 值)。
1 2 3 4 5 6 7 8 9 10 11 12 | [Authorize] public IActionResult Index() { if (User.IsInRole("SomeRole")) { return RedirectToAction("SomeAction","SomeController"); } else { return RedirectToAction("Forbidden","Error"); } } |
阅读其他一些帖子论坛和主题,我发现这可能是一个上下文持久性问题,我试图在我的帐户控制器中使用此代码解决:
1 2 3 4 5 6 7 8 9 10 11 | public async Task Login(string returnUrl ="/") { await HttpContext.ChallengeAsync( "OIDC", new AuthenticationProperties { AllowRefresh = false, IsPersistent = true, RedirectUri = returnUrl }); } |
一些例子说我可以使用
1 2 | InvalidOperationException: only a single identity supported IdentityServer4.Hosting.IdentityServerAuthenticationService.AssertRequiredClaims(ClaimsPrincipal principal) |
总而言之,我必须找到一种方法来保留我添加到用户声明列表中的角色声明,但直到现在我都没有成功。
更新一下,如果这对任何人有用。
我推断出
实际上,我确实注意到有一个
一段时间后,我发现以下解决方案对我来说效果很好:
代替
1 2 3 |
我试过
1 2 3 4 5 6 7 8 9 | var identity = context.Principal.Identity as ClaimsIdentity; if(identity != null) { var listRoles = GenericProxies.RestGet<List<string>>(urlGetRoles, response.AccessToken); // GET request to API foreach (var role in listRoles) { identity.AddClaim(new Claim(ClaimTypes.Role, role)); } } |