简体   繁体   English

如何在 Asp.Net Core 3.1 中为现有 HttpContext 用户保留新添加的声明

[英]How to persist newly added claims to existing HttpContext user in Asp.Net Core 3.1

I am new to .Net Core and have configured authentication as follow in Startup.cs file -我是 .Net Core 的新手,并在Startup.cs文件中按如下方式配置了身份验证 -

public void ConfigureServices(IServiceCollection services)
    {
        // To be able to access HttpContext
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();            

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o => o.LoginPath = "/login");

        // Most of the code removed for brevity            
    }

After user login, we authenticate the user by -用户登录后,我们通过 -

public static async Task AuthenticateUserAsync(HttpContext httpContext, AuthorizedUser authorizedUser)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, authorizedUser.UserUid.ToString()),
            new Claim(CustomClaimTypes.CompanyGuid, authorizedUser.CompanyUid.ToString())
        };

        var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

        var authProperties = new AuthenticationProperties
        {
            // Refreshing the authentication session should be allowed.
            //AllowRefresh = <bool>,

            // The time at which the authentication ticket was issued.
            IssuedUtc = DateTimeOffset.UtcNow,

            // The time at which the authentication ticket expires. A 
            // value set here overrides the ExpireTimeSpan option of 
            // CookieAuthenticationOptions set with AddCookie.
            ExpiresUtc = DateTimeOffset.UtcNow.AddHours(1),

            // Whether the authentication session is persisted across 
            // multiple requests. When used with cookies, controls
            // whether the cookie's lifetime is absolute (matching the
            // lifetime of the authentication ticket) or session-based.
            IsPersistent = false,

            //RedirectUri = <string>
            // The full path or absolute URI to be used as an http 
            // redirect response value.
        };

        await httpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(claimsIdentity),
            authProperties);
    }

In some service class, we retrieve portal information and tried to save it in claims as follow -在某些服务类中,我们检索门户信息并尝试将其保存在声明中,如下所示 -

public async Task AddPortalToCurrentUserClaimsAsync(Guid companyUid, Guid userUid)
    {
        var portal = await _unitOfWork.Portals.All().FirstOrDefaultAsync(p => p.CompanyUid == companyUid && p.UserUid == userUid).ConfigureAwait(false);
        if (portal == null) return;

        var claims = new List<Claim>
        {
            new Claim(CustomClaimTypes.PortalId, portal.Id.ToString()),
            new Claim(CustomClaimTypes.PortalName, portal.Name)
        };

        var claimsIdentity = new ClaimsIdentity(claims);
        _httpContextAccessor.HttpContext.User.AddIdentity(claimsIdentity);
    }

When I tried to retrieve this claim in further requests, I get null.当我尝试在进一步的请求中检索此声明时,我得到了空值。

var portalId = _httpContextAccessor.HttpContext.User.FindFirst(CustomClaimTypes.PortalId);
var portalName = _httpContextAccessor.HttpContext.User.FindFirst(CustomClaimTypes.PortalName);

How I can get these newly added claims to persist in further requests?我怎样才能让这些新添加的声明坚持进一步的请求?

I read from the article that share我从分享的文章中读到

To create a cookie holding user information, construct a ClaimsPrincipal .要创建保存用户信息的 cookie,请构造ClaimsPrincipal The user information is serialized and stored in the cookie.用户信息被序列化并存储在cookie中。 SignInAsync creates an encrypted cookie and adds it to the current response. SignInAsync创建一个加密的 cookie 并将其添加到当前响应中。 If AuthenticationScheme isn't specified, the default scheme is used.如果未指定AuthenticationScheme ,则使用默认方案。

So, you cannot add claims to already created ClaimsPrincipal as claims have already been stored in cookies.因此,您不能向已创建的ClaimsPrincipal添加声明,因为声明已存储在 cookie 中。

The solution that work for me was to create new ClaimsPrincipal and create new cookie as -对我ClaimsPrincipal解决方案是创建新的ClaimsPrincipal并创建新的 cookie 作为 -

public async Task AddPortalToCurrentUserClaimsAsync(Guid companyUid, Guid userUid)
        {
            var portal = await _unitOfWork.Portals.All().FirstOrDefaultAsync(p => p.CompanyUid == companyUid && p.UserUid == userUid).ConfigureAwait(false);
            if (portal == null) return;

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, userUid.ToString()),
                new Claim(CustomClaimTypes.CompanyGuid, companyUid.ToString()),
                new Claim(CustomClaimTypes.PortalId, portal.Id.ToString()),
                new Claim(CustomClaimTypes.PortalName, portal.Name)
            };

            var authProperties = new AuthenticationProperties
            {
                IssuedUtc = DateTimeOffset.UtcNow,
                ExpiresUtc = DateTimeOffset.UtcNow.AddHours(1),
                IsPersistent = false
            };

            const string authenticationType = "Cookies";
            var claimsIdentity = new ClaimsIdentity(claims, authenticationType);
            await _httpContextAccessor.HttpContext.SignInAsync(authenticationType, new ClaimsPrincipal(claimsIdentity), authProperties);
        }

Claims are only added on persisted in the ClaimsPrinciple/User if SignInAsync has been called again.声明中只添加上在ClaimsPrinciple /用户如果坚持SignInAsync再次被调用。 So, your first claims will be found because that are added before the user is signed in. However, as you're adding more claims, they won't be "saved" as the user's identity has not been reset.因此,将找到您的第一个声明,因为它是在用户登录之前添加的。但是,随着您添加更多声明,它们不会被“保存”,因为用户的身份尚未重置。

If you're adding more claims, prior to the initial sign in, this should work:如果您要添加更多声明,在初始登录之前,这应该有效:

var authProperties = new AuthenticationProperties
{
    IssuedUtc = DateTimeOffset.UtcNow,
    ExpiresUtc = DateTimeOffset.UtcNow.AddHours(1),
    IsPersistent = false,
};

await httpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    _httpContextAccessor.HttpContext.User,
    authProperties);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM