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

时间:2019-06-06 09:35:13

标签: authentication asp.net-core asp.net-core-2.2

我确实找到了类似的问题,但是所提供的答案都没有帮助我。

我确实按照教程将身份添加到我的ASP.net Core 2.2项目(https://retifrav.github.io/blog/2018/03/20/csharp-dotnet-core-identity-mysql/

即使SignInManager.PasswordSignInAsync()成功,但_Layout视图中的User.Identity.IsAuthenticated和SignInManager.IsSignedIn(User)均为假。

_Layout.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<MySiteUser> SignInManager
@inject UserManager<MysiteUser> UserManager

......................

<div>
            @if (SignInManager.IsSignedIn(User))
            {
                <div>Hello @UserManager.GetUserName(User)!</div>
            }

            @if (User.Identity.IsAuthenticated)
            {
                <div>User is authenticated </div>
            }


 </div>

在Startup.CS的ConfigureServices中,我有:

services.AddIdentity<MySiteUSer, MySiteRole>().AddEntityFrameworkStores<IdentityContext>().AddDefaultTokenProviders();


            services.Configure<IdentityOptions>(options =>
            {
                options.Password.RequireDigit = true;
                options.Password.RequiredLength = 8;
                options.Password.RequireNonAlphanumeric = true;
                options.Password.RequireUppercase = true;
                options.Password.RequireLowercase = true;

                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
                options.Lockout.MaxFailedAccessAttempts = 10;

                options.User.RequireUniqueEmail = true;
            });

            services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/Login");            

            services.AddMvc();

在Startup.CS的Configure()中,我有:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider services)
        {
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseAuthentication(); ;

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

        }

在AccountController中,我有:

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");

            if (ModelState.IsValid)
            {

                var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");                   

                    var user = await _signInManager.UserManager.FindByNameAsync(model.Username);
                    var userPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
                    var identity = userPrincipal.Identity;
                    if(identity.IsAuthenticated)                       
                      return RedirectToAction("Index", "Home");
                }

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

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

MySiteUser和MySiteRole只是覆盖默认的Identity类

public class MySiteUser : IdentityUser<int>
    {
    }

 public class MySiteRole : IdentityRole<int>
    {
    }

编辑:

由于所有答复都是关于控制器的,因此在此之前,我在AccountController中使用了以下代码

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");

            if (ModelState.IsValid)
            {

                var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false);
                if (result.Succeeded)
                {                                         
                      return RedirectToAction("Index", "Home");
                }

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

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

结果相同。

3 个答案:

答案 0 :(得分:0)

在将用户重定向到首页之前,您无需检查if(identity.IsAuthenticated)。如果代码到达(result.Succeeded)块,则表示用户已通过身份验证。 if(identity.IsAuthenticated)仅在请求结束时为true,表示您已返回HttpResponse(或其他内容),它将在客户端创建cookie。

因此解决方案是删除Login动作中的条件。

                /*if(identity.IsAuthenticated) <===== remove this */
                  return RedirectToAction("Index", "Home");

编辑:请不要忘记,当您使用RedirectToAction时,它仍然是相同的请求,因此尚未创建cookie。相反,请像往常一样创建和使用临时成功视图。

  /*if(identity.IsAuthenticated)  <===== remove this */
   return RedirectToAction("Index", "Home"); <===== remove this */
   /*put url in viewbag or use returnUrl variable*/
  @ViewBag.ReturnUrl = Url.Action("index","home"/*,null,Request.Url.Scheme*/);
  return View("LoginSuccess");

这是要放入 LoginSuccess.cshtml 视图中的内容

  <h2>Authenticated. Wait 2 seconds or click continue</h2>
  <p><a href="@ViewBag.ReturnUrl">
     Continue</a></p>

   <script>
     setTimeout(function () {
         window.location = "@ViewBag.ReturnUrl";
        }, 2000)
   </script>

PS:您可能需要使用局部视图,以避免与布局页面标题冲突... return PartialView("LoginSuccess");

答案 1 :(得分:0)

我只是找到了一个解决方案,尽管我不明白它为什么起作用。我已经检查了Chrome开发者工具,看看是否设置了身份验证Cookie。 在删除网站的所有cookie后,该应用程序设置了cookie,并且一切正常。

我还测试了更简单的AccountController,它也可以正常工作:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");

        if (ModelState.IsValid)
        {

            var result = await _signInManager
              .PasswordSignInAsync(model.Username, model.Password,
                Model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {                                         
                  return RedirectToAction("Index", "Home");
            }

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

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

答案 2 :(得分:0)

我相信我已经迷失了这个答案。首先在IE中尝试此方法,它可能在那里工作。显然,Chrome浏览器对于用于身份验证的Cookie非常挑剔,除非您在HTTPS中与之对话。如果您正在开发中,并且正在使用HTTP和Chrome,则IsSignedIn(User) 可能会失败。令人难以置信的是,这令人讨厌,并且会大大降低生产率。 HTH

相关问题