我想在会话期间使用cookie来存储userId,以避免不必要的往返数据库。此userId用于访问某些特定于用户的信息。由于cookie可以轻松编辑,我现在对安全问题很感兴趣。
为了禁止登录用户编辑他们的userId,以便访问其他用户的信息,我使用了一种非常简单的方法。我在userId cookie创建时添加了一个cookie,它存储了一个哈希值。在散列时,我使用硬编码的64字节密钥。从cookie中检索userId时,始终检查它是否与其散列值匹配。
这基本上是我的代码:
public static int GetUserId(Page page)
{
int userId;
if (page.Request.Cookies["userId"] != null && page.Request.Cookies["userIdHashed"] != null)
{
string userIdHashed = page.Request.Cookies["userIdHashed"].Value;
string userIdCoockie = page.Request.Cookies["userId"].Value;
string coockie = (userIdCoockie + "945AFF2FD0F1D89B4B1DBEB1B0C5D3B8B5DCE000AAEA331EB0C3F3A68C3865EFA73BC6EBF30C8DF1AD6B9ECB7094DA5B0C1AF36B5BBD096E3D873E9589E3F664").GetHashCode().ToString();
if (userIdHashed == coockie)
{
userId = Int32.Parse(userIdCoockie);
}
else
{
throw new Exception("UserId does not match!");
}
}
else
{
userId = ...//here userId is being retrieved from the data base and than:
page.Response.Cookies["userId"].Value = userId.ToString();
page.Response.Cookies["userId"].HttpOnly = true;
string userIdHashed = (userId.ToString() + "945AFF2FD0F1D89B4B1DBEB1B0C5D3B8B5DCE000AAEA331EB0C3F3A68C3865EFA73BC6EBF30C8DF1AD6B9ECB7094DA5B0C1AF36B5BBD096E3D873E9589E3F664").GetHashCode().ToString();
page.Response.Cookies["userIdHashed"].Value = userIdHashed;
page.Response.Cookies["userIdHashed"].HttpOnly = true;
}
return userId;
}
所以我的问题是:
可以考虑采用这种方法 在这种情况下足够可靠吗?
如果不是,我应该修改它以及如何或 我应该寻找不同的东西吗? (例如,通过加密/解密 System.Security.Cryptography为 建议here)?
还有一个问题:设置HttpCookie.HttpOnly = true以防止javascript访问cookie是否真的有意义,因为它也可以被用户轻松修改?
更新
非常感谢Kerrek SB和Darin Dimitrov的答案,他们认为考虑到已经建立了保护机制以保存这类信息,我自己尝试保护cookie是没有意义的。回传。
建议的选项是:
cache
(但我认为通常应该这样做
存储应该在用户之间共享的信息,所以我看一下
其他两个选项)。FormsAuthenticationTicket
。Session State
。所以目前我正在决定后两者之间。
更改FormsAuthenticationTicket并不是很简单。此外,它不适用于无Cookie表单身份验证(如here所述)。
使用会话状态要容易得多,但它会影响性能,因为它会将值存储在服务器内存中。但是在我的情况下它可能不那么引人注目,因为我们只存储int类型的userId。
所以现在最后一个选项对我来说看起来好多了。但是,如果有其他人可以评论,支持或批评所讨论的任何选项,我将不胜感激。
提前致谢!
答案 0 :(得分:3)
你似乎在这里重新发明了一些轮子。虽然在执行某些标准代码时可能可接受,但在涉及安全性时,这几乎总会导致灾难性后果。
要跟踪有效登录用户,我建议您使用forms authentication(此处是另一个useful tutorial)。它使用身份验证cookie来跟踪用户。这些cookie由框架安全加密,因此无法使用服务器<machineKey>
文件的machine.config
部分对其进行修改。
构建代码,只需访问当前登录的用户名即可:
public static string GetUserId(HttpContextBase context)
{
if (context == null || !context.User.Identity.IsAuthenticated)
{
return null;
}
return context.User.Identity.Name;
}
你真的不应该手动处理所有这些东西,特别是当ASP.NET框架有一个内置的机制时。
答案 1 :(得分:2)
那非常迂回而且模糊不清。如果您已经有一个活动会话,为什么不在服务器端会话数据中存储这种数据(客户端从不需要知道,请注意)?
您真正需要与客户交换的所有内容都是会话ID。
答案 2 :(得分:0)
您还可以使用安全套接字层加密Cookie
HttpCookie cookie = new HttpCookie();
cookie.Secure = true;