微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何正确实现记住我的功能? Asp.Net 核心

如何解决如何正确实现记住我的功能? Asp.Net 核心

我已经尝试了 2 天来知道如何构建记住我的功能,但没有任何明确的内容
首先,我想确保我们正确地同意此工作流程如下。

我需要在这里允许用户打开他们的个人资料而无需 重新登录 1 个月,只要用户退出

  1. 我使用基于 cookie 的身份验证来存储一些数据,我可以在每次打开用户配置文件时检查这些数据以确保用户通过身份验证。
    -- 这一步没有问题

  2. 在这一步中使用简单的代码再次从 cookie 中检索数据。
    ——问题来了。只要我登录,我就可以从 cookie 中检索数据,否则,当我停止并重新运行应用程序并直接重定向用户配置文件而无需再次登录时,我无法读取 cookie 数据,尽管它仍然存在!! !

现在我们来看看代码

启动文件 Cookie 设置

 public void ConfigureServices(IServiceCollection services){
 .....
 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
 .AddCookie(options => {
     options.Cookie.Name = "RememberMecookie"; // cookie name
     options.LoginPath = "/Account/LogIn"; // view where the cookie will be issued for the first time
     options.ExpireTimeSpan = TimeSpan.FromDays(30); // time for the cookei to last in the browser
     options.SlidingExpiration = true; // the cookie would be re-issued on any request half way through the ExpireTimeSpan
     options.EventsType = typeof(CookieAuthEvent);
 });
 .....
 }

 public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
 {
 .....
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseCookiePolicy();
    app.UseEndpoints(endpoints =>
    {
      endpoints.MapDefaultControllerRoute();
    }
  .....

  public class CookieAuthEvent : CookieAuthenticationEvents
  {
      public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
      {
          context.Request.HttpContext.Items.Add("ExpiresUTC",context.Properties.ExpiresUtc);
      }
  }

  }

登录viewmodel

public class VMLogin
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

控制器/登录

    [HttpPost]
    public async Task<IActionResult> LoginAsync(VMLogin CurrentUserLog,string returnUrl)
    {
        if (!string.IsNullOrEmpty(CurrentUserLog.UserName) && string.IsNullOrEmpty(CurrentUserLog.Password))
        {
            return RedirectToAction("Login");
        }

        if (ModelState.IsValid)
        {
            var SignInStatus = await signInManager.PasswordSignInAsync
                (CurrentUserLog.UserName,CurrentUserLog.Password,CurrentUserLog.RememberMe,false);
            AppUser _user = await userManager.FindByNameAsync(CurrentUserLog.UserName);
            if (SignInStatus.Succeeded)
            {
                if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)) // to prevent login from outside link
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    var claims = new List<Claim>
                    {
                        new Claim(ClaimTypes.Name,CurrentUserLog.UserName),new Claim(ClaimTypes.Email,_user.Email),new Claim(ClaimTypes.NameIdentifier,_user.Id.ToString())
                    };
                    
                    var identity = new ClaimsIdentity(claims,CookieAuthenticationDefaults.AuthenticationScheme);
                    var principal = new ClaimsPrincipal(identity);
                    var props = new AuthenticationProperties{ 
                        IsPersistent = true,ExpiresUtc = DateTime.UtcNow.AddMonths(1)
                    };
                    
                    // to register the cookie to the browser
                    HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,principal,props).Wait();

                    return RedirectToAction("UserProfile");
                }
            }

            ModelState.AddModelError(string.Empty,"Invalid Login Attempt");
        }
        return View(CurrentUserLog);
    }

所有问题都在这里当我第一次登录时,我从 cookie 中获取数据,第一次创建 cookie,如图所示 上面的代码。但是,我无法从相同的日期获得相同的日期 cookie 当我停止调试并再次运行应用程序,并重定向到 UserProfile 直接无需登录,虽然 cookie "RememberMecookie" 仍然存在。

控制器/用户配置文件

    [Authorize]
    public async Task<IActionResult> UserProfile()
    {
        // all lines of code below are working just with the first creation of the cookie with the first login. but if rerun the app again,they all return null if redirect here directly without logIn.

        string userId = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value;

        Claim v = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);

        AppUser _user = await userManager.GetUserAsync(HttpContext.User);

        string cookieValueFromreq = Request.Cookies["RememberMecookie"];

        // this is for normal login without remember me functionality
        //AppUser user = await userManager.GetUserAsync(User);
        return View(/*user*/);
    }

解决方法

感谢所有花时间检查我的问题的人。我终于找到了问题所在。这段代码真的很棒,它可以作为使用基于 cookie 的身份验证记住我的功能的一个很好的参考。而且代码本身没有问题。

问题出在我的启动文件

原来是这样

services.AddMvc(config =>
{
    var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
    config.Filters.Add(new AuthorizeFilter(policy));
});

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => {
    options.Cookie.Name = "RememberMeBlogAcademy";
    options.LoginPath = "/Account/LogIn";
    //options.LogoutPath = "/Home/Index";
    //options.AccessDeniedPath = "AccessDenied";
    options.ExpireTimeSpan = TimeSpan.FromDays(30);
    options.SlidingExpiration = true; // the cookie would be re-issued on any request half way through the ExpireTimeSpan
    //options.Cookie.Expiration = TimeSpan.FromDays(5);
    options.EventsType = typeof(CookieAuthEvent);
});
//services.AddScoped<CookieAuthEvent>();

 services.AddControllersWithViews();

问题是一起使用 MVC 和 AddControllersWithViews。我不知道这会产生问题。

然而,它应该是这样的——使用 AddControllersWithViews

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => {
            options.Cookie.Name = "RememberMeBlogAcademy";
            options.LoginPath = "/Account/LogIn";
            //options.LogoutPath = "/Home/Index";
            //options.AccessDeniedPath = "AccessDenied";
            options.ExpireTimeSpan = TimeSpan.FromDays(30);
            options.SlidingExpiration = true; // the cookie would be re-issued on any request half way through the ExpireTimeSpan
            //options.Cookie.Expiration = TimeSpan.FromDays(5);
            options.EventsType = typeof(CookieAuthEvent);
});
services.AddScoped<CookieAuthEvent>();

services.AddControllersWithViews(config =>
{
     var policy = new AuthorizationPolicyBuilder()
         .RequireAuthenticatedUser()
         .Build();
     config.Filters.Add(new AuthorizeFilter(policy));
});

此外,您不需要从 cookie 中检索数据,如上面的 Controller/UserProfile 所示。

此外,当我进行调试以检查代码时,我测试了注销以确保我真的从 cookie 中检索用户数据,而不是从 UserManager 中检索用户数据,并且它确实运行良好。

这里是注销的附加代码

[Authorize]
public async Task<IActionResult> Logout()
{
    await signInManager.SignOutAsync();
    await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    return RedirectToAction("Index","Home");
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。