繁体   English   中英

我可以通过使用 cookies -> Asp.Net-Core Identity(实时部署)自动重新登录到我的 SignInManager 和 UserManager(身份)

[英]Can I automatically log back into my SignInManager and UserManager (Identity) via using cookies -> Asp.Net-Core Identity (Deployed live)

主要问题是:我可以通过使用 cookies 自动重新登录到我的 SignInManager 和 UserManager(身份)吗? 如果这是不可能的,你会推荐什么作为替代方案?

所以,这里的主要问题归结为我的专用 IIS 池在 5 分钟后终止了工作程序; 现在我可以将其配置为基于会话的,但由于它是共享服务器,这带来了一个全新的问题领域。
当工作人员被终止时,session 到期,所有登录用户都将注销。 但是,我们仍然有 cookies。
值得注意的是,我的目标框架是“netcoreapp3.1”,并且这个项目的部署是在一个实时服务器上。

让我们深入研究您需要了解的主要内容:
登录 Function(路径:/Account/Login):

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
    {       
        if (ModelState.IsValid)
        {
            var result = await signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, false);
            if (result.Succeeded)
            {
                if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }

            ModelState.AddModelError(String.Empty, "Invalid Login Attempt");
        }
        return View(model);
    }

接下来是相关的启动,在ConfigureServices中:

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
         {
             options.Password.RequiredLength = 3;
             options.Password.RequiredUniqueChars = 0;
             options.Password.RequireNonAlphanumeric = false;
             options.Password.RequireLowercase = false;
             options.Password.RequireUppercase = false;
             options.Password.RequireDigit = false;

         }).AddEntityFrameworkStores<AppDbContext>().AddDefaultTokenProviders();

services.ConfigureApplicationCookie(e =>
        {   
            e.LoginPath = new PathString("/Account/Login");
            e.LogoutPath = new PathString("/Account/Logout");
            e.AccessDeniedPath = new PathString("/Account/AccessDenied");
            e.Cookie.MaxAge = TimeSpan.FromDays(3);
            e.ExpireTimeSpan = TimeSpan.FromDays(3);
            e.Cookie.HttpOnly = true;
            e.SlidingExpiration = true;
            e.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
        });

在配置中:

app.UseAuthentication();

AddIdentity 默认调用 services.AddAuthentication();
这将创建您的标准样板 Identity.Application Cookie,而 session 不会终止或崩溃,它将让您保持登录 3 天; 自然地,因为我们的 session 确实过期了,这将在 5 分钟内终止。 因此,在开始时重申问题,是否可以使用我们拥有的 cookie 让用户保持登录(或重新登录),以便用户不会受到 session 到期的不利影响?

那么,我在我想要部署的功能上是否存在根本缺陷,或者这是否可以通过一些工作来解决?
我遇到的相当多的“解决方案”没有办法重新登录到 SignInManager/UserManager 或者已经被弃用。

这里的任何建议都会受到极大的赞赏::)

现在我设法为此创建了一个解决方案,首先我会说虽然它有效,但它有自己的一系列问题(主要是安全问题)。

在此值得说明的是,我已经有一个 ApplicationUser 设置,如果你没有,那么你需要创建它来扩展 IdentityUser 以将 cookieId 字段添加到你的身份数据库中。

第一步是为用户创建一种通过 cookies 登录到 signInManager 的方式,我们通过扩展 UserManager class 来实现这一点:

 public static class UserManagerExtensions
{
    public static async Task<ApplicationUser> FindByCookieAsync(this UserManager<ApplicationUser> um, string cookieId)
    {
        return await um?.Users?.SingleOrDefaultAsync(x => x.CookieId.Equals(cookieId));
    }
}

这允许我们检索将用于登录的 ApplicationUser。

下一步是设置这个 cookie,我们通过将以下代码应用到我们的登录和注册来做到这一点(如果您的注册自动登录用户):

var cookieVal = generateRandomCookieValue();
                HttpContext.Response.Cookies.Append("CookieName", cookieVal, new Microsoft.AspNetCore.Http.CookieOptions
                {
                    Expires = DateTimeOffset.UtcNow.AddDays(7),
                    HttpOnly = true,
                    Secure = true,
                    SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax
                }) ;

                if (cookieVal != null)
                {

                    ApplicationUser userModel = await userManager.FindByNameAsync(model.Username);
                    userModel.CookieId = cookieVal;
                    await userManager.UpdateAsync(userModel);
                }

当用户注销时,我们只需从 header 中删除此 cookie 并从数据库中清除存储的 cookie。 这部分在我们的 Logout 方法中被调用:

 HttpContext.Response.Cookies.Delete("CookieName");
        ApplicationUser userModel = await userManager.FindByNameAsync(User.Identity.Name);
        userModel.CookieId = null;
        await userManager.UpdateAsync(userModel);

就个人而言,我在用户成功登录后使用此代码块。由于我们没有在 cookie 中存储任何数据,而只是将其用作密钥,因此我们不需要复杂的 cookie,但我更喜欢模仿Identity.Application 的 cookie 的长度。

private string generateRandomCookieValue()
    {
        StringBuilder returnString = new StringBuilder();
        Random rand = new Random();
        for (int i = 0; i < 646; i++)
        {
            var x = rand.Next(48, 124);
            if((x<58 || x>64) && (x<91 || x > 96))
            {
                if (x == 123)
                {
                    returnString.Append('-');
                }
                else if (x == 124)
                {
                    returnString.Append('_');
                }
                else
                {
                    returnString.Append((char)x);
                }
            }
            else
            {
                if (i != 0)
                {
                    i--;
                }
            }
        }
        return returnString.ToString();
    }

现在我们在用户登录后的 1 周内创建了 cookie,我们需要一种方法来检查每个请求的状态,以使用户重新登录。在我们的启动配置方法中,我们添加以下块:

app.Use(async (context, next) =>
        {
            var cookie = context.Request.Cookies["CookieName"];
            var userAuth = context.User.Identity.IsAuthenticated;
            if (cookie != null && !userAuth)
            {
                context.Request.Method = "POST";
                context.Request.Path = "/Account/AutoLogin";
            }
            await next();
        });

        app.UseRouting();

为此,我们需要添加“UseRouting()”方法。 我们正在使用此方法指向最后一步的 AutoLogin 方法。

[HttpPost]
    public async Task<IActionResult> AutoLogin()
    {
        var cookie = HttpContext.Request.Cookies["CookieName"];
        var user = await userManager.FindByCookieAsync(cookie);
        if(user != null)
        {
            await signInManager.SignInAsync(user, true);

            //If you want to configuring sliding expiration (which essentially issues a new cookie), you will need to manually do it here
            //Using the same setup we used in login, and then propagate that update to the database.
            var y = HttpContext;
            return RedirectToAction("Index", "Home");
        }
        else
        {
            HttpContext.Response.Cookies.Delete("CookieName");
            return RedirectToAction("Index", "Home");
        }            
    }

在我们的 autoLogin 方法中,我们可以通过创建一个新的 cookie 并更新数据库中的用户来手动创建一个滑动过期,这个过程类似于登录。

类似一个session,存在安全问题,如果你有用户的cookie,你可以以他们的身份登录,我想不出这个解决方案的办法,添加自定义滑动过期以发出新的cookie轻微增加它。 非常推荐安全连接。

我希望它有助于指导任何人为面临相同问题的人找到可能更好的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM