首页 > 解决方案 > HttpContext.SignInAsync() 无法设置 cookie 并返回 User.Claims

问题描述

我写了一个网站,可以从 Discord 执行 SSO。我正在尝试仅通过 cookie 使用登录系统。我似乎无法设置 cookie 并返回 User.Claims。我在下面提供了 Startup.cs 和我的登录文件。预先感谢您。

 var tempId = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
            tempId.AddClaim(new Claim("state", state));
            tempId.AddClaim(new Claim("nonce", nonce));

            //HttpContext.Request.GetOwinContext().Authentication.SignIn(tempId);
            var authProperties = new AuthenticationProperties
            {
                AllowRefresh = true,
                ExpiresUtc = DateTimeOffset.Now.AddDays(1),
                IsPersistent = true,
            };

            var principal = new ClaimsPrincipal(tempId);
             HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

            var claim = HttpContext.User.Claims;

地位


            services.AddSession();
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.ConsentCookie.IsEssential = true;
             
                options.CheckConsentNeeded = context => false;
               
            });

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                     .AddCookie(options =>
                     {
                         options.Cookie.Name = "Cookie";
                         options.Cookie.IsEssential = true;
                         options.Cookie.HttpOnly = true;
                         options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
                        
                         options.LoginPath = new PathString("/account/login");
                         options.LogoutPath = new PathString("/account/logout");
                         options.ExpireTimeSpan = TimeSpan.FromDays(1);
                         options.SlidingExpiration = false;
                     });

            services.AddMvc(options =>
            {
                options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
            }).SetCompatibilityVersion(CompatibilityVersion.Latest); ;


            app.UseSession();
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });

标签: c#asp.net-core

解决方案


正如 abdusco 所说,在 login 方法中,在添加claimsClaimsPrincipal并调用该HttpContext.SignInAsync()方法登录后,您声称不会在 current 中更新HttpContext.User。因此,如果您直接从 获得索赔HttpContext.User,则为空。

如果要访问登录页面中的声明(在调用HttpContext.SignInAsync()方法之后),可以从 中获取声明principal,代码如下:

     #region snippet1
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.Name, user.Email),
        new Claim("FullName", user.FullName),
        new Claim(ClaimTypes.Role, "Administrator"),
    };

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

    var authProperties = new AuthenticationProperties
    {
         //...
    };
    var principal = new ClaimsPrincipal(claimsIdentity);
    await HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme, 
        new ClaimsPrincipal(claimsIdentity), 
        authProperties);
    #endregion

    var userclaims = principal.Claims;

结果如下:

在此处输入图像描述

如果您想从 中获取声明HttpContext.User,您应该从下一个请求中获取它们。

请参考cookie认证文档官方示例代码

Login.cshtml.cs 文件的 post 方法中,它将向用户添加声明。

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        ReturnUrl = returnUrl;

        if (ModelState.IsValid)
        {
            // Use Input.Email and Input.Password to authenticate the user
            // with your custom authentication logic.
            //
            // For demonstration purposes, the sample validates the user
            // on the email address maria.rodriguez@contoso.com with 
            // any password that passes model validation.

            var user = await AuthenticateUser(Input.Email, Input.Password);

            if (user == null)
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return Page();
            }

            #region snippet1
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.Email),
                new Claim("FullName", user.FullName),
                new Claim(ClaimTypes.Role, "Administrator"),
            };

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

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

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

                //IsPersistent = true,
                // 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.

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

                //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);
            #endregion

            _logger.LogInformation("User {Email} logged in at {Time}.", 
                user.Email, DateTime.UtcNow);

            return LocalRedirect(Url.GetLocalUrl(returnUrl));
        }

        // Something failed. Redisplay the form.
        return Page();
    }

然后,在联系页面(需要身份验证)中,我们可以从以下位置访问声明HttpContext.Claims

在此处输入图像描述


推荐阅读