ASP.NET Identity非常复杂,对于我在ASP.NET MVC 5应用程序中所需要的内容来说,它过于夸张了。保持简单是IMHO的一个好原则。
当用户登录时,我只需使用Dapper来查找电子邮件&数据库中的密码(使用哈希和salting)。
然后我设置了一个会话["userID"]=user。Id//来自数据库。
这个Id是一个高熵随机生成的字符串(即一个可以撤销的安全戳,而不是实际的用户Id),会话超时设置为长时间(例如1个月),因此用户不必继续登录。
在用户是管理员的情况下,我也只是将会话["admin"]=true;
然后我创建一个简单的类,它继承自AuthorizeAttribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.Session["userID"] == null)
return false;
else
return true;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectResult("~/Account/Login");
}
}
这样我就可以在我的控制器上使用授权属性:
[MyAuthorize]
public ActionResult MyController()
{
...
}
这安全吗?我有没有遗漏任何步骤来确保这一点——如果有,怎么办?
这是不是出了什么问题,会在操作中失败?
会话能够做到这一点吗?如果不是,什么是&有什么更好的方法(同样简单)?
首先,我不同意你关于复杂性的评论。到目前为止,ASP.Net Identity是.Net最全面、最完善的身份验证/授权框架。它优于所有的前辈,具有许多可能的扩展点。如果你认为这非常复杂,那么就考虑一下一般的安全性——这是一个非常复杂的领域,涉及的风险很高。身份框架实际上简化并隐藏了许多复杂性,所以您不必处理这些问题。如果你仍然坚持认为这很复杂。。。是的,软件开发是一项复杂的业务。一般来说,计算是复杂的。。。生活是复杂的!
无论如何,回到您的解决方案。我可以看到您的解决方案中至少有一个主要缺陷。您通过会话cookie对用户进行身份验证。你提议这次会议是一次很长时间的会议。这意味着会话cookie在很长一段时间内不会更改。因此,如果有人以某种方式获得了对会话的访问权限,他们将有很长的机会像其他人一样滥用对您系统的访问权限。Identity通过旋转cookie来解决这个问题——默认情况下,每30分钟更改一次authcookie值。所以,如果你得到某人昨天的饼干价值,那就没有什么好处了。您还可以将该值减少到几分钟,甚至可以在每次请求时更新cookie值。
然后,您需要考虑会话到期和管理。首先,这将占用内存——对于过去30天内登录的每个用户,您都必须在服务器上维护实时会话。想象一下,有一千个用户登录……我不知道每个用户会话会有多少数据,但如果使用足够多,你就会开始遇到内存问题。然后,如果你想对服务器进行负载平衡,你就必须引入一个粘性会话。此外,当你的服务器重新启动时,所有用户都会失去他们的会话(我用过这种系统——这太可怕了)。
接下来,你必须处理多个用户登录——当同一用户从两个不同的浏览器登录时会发生什么?当用户更改密码时,用户会话会发生什么?如何注销其他浏览器?
我还没有做大量的会话工作,所以我不确定会话cookie是如何创建的。但是查看文档(会话标识符部分)sessionId存储在cookie中。您建议将User.Id放入会话cookie中这意味着,如果攻击者知道User.Id
,那么他们可以随时以该用户身份登录为了缓解这种情况,您必须想出一种方法,将用户id隐藏在会话中,并使用某种关联id,即使这样,您也无法避免这样一个事实,即一旦创建了关联id,它将持续整个会话寿命-30天。谈论复杂的解决方案?
Identity为您提供了许多开箱即用的功能。你现在可能不需要但将来可能需要的东西。对于本土解决方案,这将是一个自己写的例子。
- 验证新注册的电子邮件
- 双因素身份验证
- 社交登录
- 密码强度要求
- 用户名/电子邮件唯一性要求
- 用户锁定
- 缓解密码共享
- 通过电子邮件链接重置密码
列表并不是详尽无遗的,只是我的一些想法。