SignInManager.PasswordSignInAsync() 成功,但 User.Identity.IsAuthenticated 为 false

Posted

技术标签:

【中文标题】SignInManager.PasswordSignInAsync() 成功,但 User.Identity.IsAuthenticated 为 false【英文标题】:SignInManager.PasswordSignInAsync() succeeds, but User.Identity.IsAuthenticated is false 【发布时间】:2019-06-30 01:24:52 【问题描述】:

我是 ASP.Net Core 的新手,正在尝试创建用户身份验证系统。我正在使用 ASP.Net Core Identity 用户管理。我有以下用于登录用户的代码。

/Areas/Identity/Pages/Account/Login.cshtml.cs

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

    returnUrl = returnUrl ?? Url.Content("~/");

    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(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);

        if (result.Succeeded)
        
            _logger.LogInformation("User logged in.");
            _logger.LogInformation(User.Identity.IsAuthenticated.ToString());

            return LocalRedirect(returnUrl);
        
        if (result.RequiresTwoFactor)
        
            return RedirectToPage("./LoginWith2fa", new  ReturnUrl = returnUrl, RememberMe = Input.RememberMe );
        
        if (result.IsLockedOut)
        
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        
        else
        
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        
    

    // If we got this far, something failed, redisplay form
    return Page();

Startup.cs

public void ConfigureServices(IServiceCollection services)

    services.Configure<CookiePolicyOptions>(options =>
    
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    );

    services.AddDbContext<ApplicationDbContext>(options =>
    
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
    );

    services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    // Use a unique identity cookie name rather than sharing the cookie across applications in the domain.
    services.ConfigureApplicationCookie(options =>
    
        options.Cookie.Name = Configuration["CookieName"];
    );

    // Add SAML SSO services.
    services.AddSaml(Configuration.GetSection("SAML"));

    services.AddTransient<IPasswordHasher<IdentityUser>, CustomPasswordHasher>();


public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    if (env.IsDevelopment())
    
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    
    else
    
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseAuthentication();

    app.UseMvc(routes =>
    
        routes.MapRoute(
            "default",
            "controller=Home/action=Index/id?");
    );

当用户登录时,我需要在 cookie 中设置一些属性,但我总是得到 User.Identity.IsAuthenticated false,即使它在记录器中显示 User logged in 并且 PasswordSignInAsync 成功。 OnPostAsync里面的用户如何登录?

注意:PasswordSignInAsync 成功后重定向到主页时用户已登录。

我已经检查了这个question,但它并没有解决我的问题。

【问题讨论】:

对我来说,当 auth 中间件设置不正确时,也会出现类似的情况。您能否在启动时也显示您的配置?可能这部分没问题,但读取身份验证信息的部分没有从正确的位置获取它。 @SamiKuhmonen 我已经添加了我的 Startup.cs 代码。你能看看吗? 我遇到了同样的问题,我意识到我拼错了用于身份验证服务的 defaultScheme。查看您的代码,我看不到带有 AddCookie services.AddAuthentication("Identity.Application").AddCookie(); 的 AddAuthentication 行 【参考方案1】:

对于User.Identity.IsAuthenticated,它只适用于PasswordSignInAsync之后的子请求。

您可以尝试以下选项:

    重定向到另一个操作以设置 cookie。

    public class LoginModel : PageModel
    
        private readonly SignInManager<IdentityUser<int>> _signInManager;
        private readonly ILogger<LoginModel> _logger;
    
        public LoginModel(SignInManager<IdentityUser<int>> signInManager, ILogger<LoginModel> logger)
        
            _signInManager = signInManager;
            _logger = logger;
        
    
        //rest code
    
        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        
            returnUrl = returnUrl ?? Url.Content("~/");
    
            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(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
                if (result.Succeeded)
                
                    _logger.LogInformation("User logged in.");
                    return LocalRedirect($"~/Identity/Account/Login?handler=SetIdentity&returnUrl=returnUrl");
                
                if (result.RequiresTwoFactor)
                
                    return RedirectToPage("./LoginWith2fa", new  ReturnUrl = returnUrl, RememberMe = Input.RememberMe );
                
                if (result.IsLockedOut)
                
                    _logger.LogWarning("User account locked out.");
                    return RedirectToPage("./Lockout");
                
                else
                
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return Page();
                
            
    
            // If we got this far, something failed, redisplay form
            return Page();
        
    
        public async Task<IActionResult> OnGetSetIdentityAsync(string returnUrl)
        
            _logger.LogInformation(User.Identity.IsAuthenticated.ToString());
    
            return LocalRedirect(returnUrl);
        
    
    

    使用_signInManager.CreateUserPrincipalAsync

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    
        returnUrl = returnUrl ?? Url.Content("~/");
    
        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(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
            if (result.Succeeded)
            
                var user = await _signInManager.UserManager.FindByEmailAsync(Input.Email);
                var userPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
                var identity = userPrincipal.Identity;
                return LocalRedirect(returnUrl);
            
            if (result.RequiresTwoFactor)
            
                return RedirectToPage("./LoginWith2fa", new  ReturnUrl = returnUrl, RememberMe = Input.RememberMe );
            
            if (result.IsLockedOut)
            
                _logger.LogWarning("User account locked out.");
                return RedirectToPage("./Lockout");
            
            else
            
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return Page();
            
        
    
        // If we got this far, something failed, redisplay form
        return Page();
    
    

【讨论】:

以上是关于SignInManager.PasswordSignInAsync() 成功,但 User.Identity.IsAuthenticated 为 false的主要内容,如果未能解决你的问题,请参考以下文章