3

我的应用程序通过 AzureAD 登录,但现在我需要从数据库中获取信息,然后将角色存储为声明。

所以我的问题是:身份验证后如何将角色存储为声明?

这是我尝试过的:

var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));  

但是当我去另一个控制器时,索赔不存在了?

谢谢

4

2 回答 2

6

您可以在身份验证期间实现这一点,在 OIDC 中间件中,OnTokenValidated您可以修改从传入令牌获得的 ClaimsIdentity,以下代码供您参考:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => Configuration.Bind("AzureAd", options));


services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
    options.Events = new OpenIdConnectEvents
    {
        OnTokenValidated = ctx =>
        {
            //query the database to get the role

            // add claims
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Role, "Admin")
            };
            var appIdentity = new ClaimsIdentity(claims);

            ctx.Principal.AddIdentity(appIdentity);

            return Task.CompletedTask;
        },
    };
});

然后在控制器中,您可以获得如下声明:

var role = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value;
于 2020-01-03T02:08:48.110 回答
0

如果OnTokenValidated用户不存在您的数据库,您可以抛出特定异常。然后OnRemoteFailure事件将用户重定向到该特定异常的特定操作方法

options.Events = new OpenIdConnectEvents()
                 {
                     OnTokenValidated = async context =>
                     {
                         
                         // get email claim
                         var emailClaim = context.Principal.Claims.SingleOrDefault(x => x.Type == ClaimTypes.Email);
                         
                         UserEntity cu = null;

                         using (var accountService = context.HttpContext.RequestServices.GetService<IAccountService>())
                         {
                             cu = await accountService.Authorize(emailClaim.Value);
                         }

                         if (cu == null)
                         {
                             throw new UnauthorizedAccessException(string.Format("Could not find user for login '{0}' ", emailClaim.Value));
                         }

                         
                         var newIdentity = new ClaimsIdentity(context.Principal.Identity.AuthenticationType);                         
                          
                         // keep the id_token for logout 
                         newIdentity.AddClaim(new Claim("id_token", context.ProtocolMessage.IdToken));

                         // add email claim
                         newIdentity.AddClaim(emailClaim);
                         
                         // add email value as name claim
                         newIdentity.AddClaim(new Claim(ClaimTypes.Name, emailClaim.Value));                         

                         // add other claims here like roles                         
                         
                         context.Properties.IsPersistent = true;
                         context.Properties.ExpiresUtc = DateTime.UtcNow.AddHours(3);

                         // overwrite existing authentication ticket
                         context.Principal = new ClaimsPrincipal(newIdentity);
                     },                     
                     OnRedirectToIdentityProviderForSignOut = async context =>
                     {
                         var idTokenHint = context.HttpContext?.User?.FindFirst("id_token");
                         if (idTokenHint != null)
                             context.ProtocolMessage.IdTokenHint = idTokenHint.Value;                         
                         await Task.FromResult(0);
                     },
                     OnRemoteFailure = async context =>
                     {
                         if (context.Failure is UnauthorizedAccessException)
                         {
                             context.Response.Redirect("/Account/UnAuthorized");
                         }
                         else
                         {
                             context.Response.Redirect("/Account/Error");
                         }
                         context.HandleResponse();
                         await Task.FromResult(0);
                     }
                 };

账户控制器.cs

   public class AccountController : Controller
   {
        [AllowAnonymous]
        public IActionResult UnAuthorized()
        {
            HttpContext.Session.Clear();
            await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(HttpContext, CookieAuthenticationDefaults.AuthenticationScheme);
            await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignOutAsync(HttpContext, OpenIdConnectDefaults.AuthenticationScheme);
        }
   }
于 2021-07-29T16:20:28.317 回答