簡體   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