首页 > 解决方案 > 使用部分身份框架在 ASP.NET Core 中存储用户 ID

问题描述

我已经使用身份框架持久 cookie(如果用户选择记住我)或会话 cookie 创建了一个登录功能,如果只是标准登录并且没有记住我被勾选。我使用以下代码:

                        var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

                    if (RememberMe)
                    {
                        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
                            new ClaimsPrincipal(claimsIdentity),
                            new AuthenticationProperties
                            {
                                IsPersistent = RememberMe,
                                ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2)
                            });
                    }
                    else
                    {
                        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
                            new ClaimsPrincipal(claimsIdentity));
                    }
                    return RedirectToPage("/index");

我在前端使用 VueJS,所以我向我的 SQL 服务器发出各种 axios POST 请求,所以我设置了一个控制器来处理这个,如下例所示:

        [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult AddFirm([FromBody] FirmModel model)
    {

        String query = "exec dbo.A2Q_Edit_0112_RR_UploadNewReview_AddFirm @FIRM_NAME, @USER_ID";
        System.Diagnostics.Debug.WriteLine("value:" + model.FIRM_NAME);
        using (var connection = new SqlConnection(connectionString))
        {
            var json = connection.QuerySingle<string>(query, new { FIRM_NAME = model.FIRM_NAME , USER_ID = USER_ID});
            return Content(json, "application/json");
        }

    }

正如您将看到的,我的控制器在我的 SQL 查询中包含一个参数,以捕获启动存储过程的用户 ID。我想存储这个变量服务器端。我已经阅读了很多帖子,似乎很多人暗示身份来处理这个问题,因为会话不可靠地存储用户数据。因此,我很好奇当我只使用有限版本的身份来制作 cookie 时如何使用身份。我不需要身份和表格等的所有开销。有没有办法使用身份来存储这些类似于会话的用户变量?如果没有,是否有使用此 cookie 存储用户 ID 或充当用户 ID 的安全方式?或者根据我的描述,在当今时代,使用 ASP.NET Core 3.1 和 IIS 8 会话是最好的吗?

这似乎是一件简单的事情,但我正在努力解决这一方面的问题,以便在我的 sql 查询参数中填充这个用户 ID 变量,而不是存储在 VueJS 的前端。

*警告我将来可能会使用 signalIR,以便根据我在堆栈上看到的帖子的理解,可以取消会话作为选项。

标签: vue.jsasp.net-coreasp.net-core-mvcasp.net-identity

解决方案


如果我的问题是正确的,那么我们需要某种机制来UserId处理每个请求。

如果是这样,请考虑将UserIdcookie 放入 cookie 中,这不是需要安全的东西,因为即使 jwt 令牌也有一个sub密钥打算保存这样的某种值。

与在 ASP 网络中使用默认.AddCookie扩展名一样,您的登录过程应该是

// Create the claims
var claims = new List<Claim>
{
    new Claim(ClaimTypes.NameIdentifier, [The UserId goes here]),
    // some other require stuff
};

// Sign in
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity),
    new AuthenticationProperties
    {
        IsPersistent = RememberMe,
        ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2)
    });

现在,userId被存储在 cookie 中,不要试图解密,这是生成后 cookie 内容的示例形式CfDJ8MblQARvMeFAppYZW16O0Qm0moCi0%2Fu77SujBcwhrmg2gAtPiCrKJEcAL3Ry%2By9Xp8subrazS5ajc%2F4dD153VZrndwSU3dVXmESF0NZxW8oWmyo5lhuGSv9LpgAuQs6pEfRJCeLXpE4%2FxU9SDzyWlk4LLf9HzxiBXTYswPZdvnLr

以及与 cookie 相关联的请求。我们可以作为 的属性userId返回。UserHttpContext

public IActionResult Index()
{
    var user = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);
    var myUserId = user.Value;
    // Then pass it along as wished
}

关于使用 SignalR:您的意思是注销用户吗?如果是这样,signalR 可以处理快乐的情况,只要应用程序仍然有足够的连接(webSocket 保持它,小心,想象大约只有 3-500 个 CCU 或更多,只是为了这个有时的任务?即使连接断开并重新连接,您仍然必须处理该逻辑)。

相反,为什么不在您登录时为 cookie 附加一个唯一密钥,该密钥会为每个登录会话重新呈现。然后有一个中间件来检查该密钥是否存在于黑名单中(将其存储为缓存会很好),我们将在这里抛出所有需要锁定的信息(只要 cookie 生命周期就过期,在这种情况下, 2小时)。

完成,没有更多的连接保持,没有更多的快乐 - 不快乐的情况以及 websocket 附带的所有那些复杂的东西。


推荐阅读