首页 文章

RedirectToAction启动新会话

提问于
浏览
2

我有一个登录我的用户的控制器 . 假设现有用户和密码正确,我检查他们是否启用了2fa .

AccountControler login method

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, _configurationSettings.LockoutOnFailure);
            if (result.Succeeded)
            {
                var user = await _userManager.FindByEmailAsync(model.Email);
                await _signInManager.SignInAsync(user, _configurationSettings.IsPersistent);
                _logger.LogInformation("User logged in.");
                return RedirectToLocal(returnUrl);
            }
            if (result.RequiresTwoFactor)
            {
                return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
            }
            if (result.IsLockedOut)
            {
                _logger.LogWarning("User account locked out.");
                return RedirectToAction(nameof(Lockout));
            }

            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return View(model);
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

假设用户确实启用了2fa,那么我将它们重定向到LoginWith2fa方法 .

[HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> LoginWith2fa(bool rememberMe, string returnUrl = null)
    {
        // Ensure the user has gone through the username & password screen first
        var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

        if (user == null)
        {
            throw new ApplicationException($"Unable to load two-factor authentication user.");
        }

        var model = new LoginWith2faViewModel { RememberMe = rememberMe };
        ViewData["ReturnUrl"] = returnUrl;

        return View(model);
    }

这是我的问题来自var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); 总是返回null . 我放了几个断点,它看起来像是在ApplicationSignInManager和AccountController中重新构建我的构造函数 . 在那里给我一个新的 Session .

SignInManager在startup.cs中注册为作用域

services.AddIdentity<ApplicationUser, IdentityRole<long>>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddSignInManager<ApplicationSignInManager>()
            .AddDefaultTokenProviders();

你如何调用RedirectToAction并保留相同的会话?

我一直关注这个项目Identity Server 4 Demo

Update: Comment about HttpContext
enter image description here

1 回答

  • 1

    感谢@muqeetkhan给我提示 . 我正在使用自定义SignInManager,它需要设置正确的会话cookie,以便将用户数据传播到下一页 .

    public class ApplicationSignInManager : SignInManager<ApplicationUser>
        {
    
            private readonly ILogger _logger;
            public ApplicationSignInManager(UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor,
                ILogger<ApplicationSignInManager> logger, IAuthenticationSchemeProvider schemes) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes)
            {
                _logger = logger;
            }
    
            public override async Task<SignInResult> PasswordSignInAsync(string userEmail, string password, bool isPersistent, bool shouldLockout)
            {
                if (UserManager == null)
                    return SignInResult.Failed;
                var result = await new FindUserCommand(_logger, UserManager, userEmail, password, shouldLockout).Execute();
    
                if (result != SignInResult.TwoFactorRequired) return result;
    
                var user = await UserManager.FindByEmailAsync(userEmail);
                return await SignInOrTwoFactorAsync(user, true);   // Required sets the session Cookie
            }
        }
    

    基本上需要调用 SignInOrTwoFactorAsync(user, true); .

相关问题