ASP.NET身份非常复杂,并且在ASP.NET MVC 5应用程序中需要的内容过于苛刻。保持简单是一个很好的原则恕我直言。
当用户登录时,我只需使用Dapper查找电子邮件&数据库中的密码(使用散列和盐析)。
然后我从数据库设置会话[" 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()
{
...
}
这样安全吗?是否有任何我缺少的步骤来确保这一点 - 如果是这样的话?
这有什么问题,它会失败吗?
会话能够做到这一点吗?如果不是什么&什么是更好的方式(这很简单)?
答案 0 :(得分:3)
首先,我不同意你对复杂性的评论。到目前为止,ASP.Net Identity是.Net最全面和最完善的身份验证/授权框架。它优于所有具有许多可扩展点的前辈。如果您认为这非常复杂,那么请考虑一般的安全性 - 这是一个涉及高风险的非常复杂的领域。身份框架实际上简化并隐藏了很多复杂性,因此您不必处理此问题。如果你仍然坚持这很复杂......嗯,是的,软件开发是一项复杂的业务。计算一般很复杂......好吧,生活很复杂!
无论如何,回到你的解决方案。我可以通过您的解决方案看到至少一个主要缺陷。您可以通过会话cookie对用户进行身份验证。你建议会议是一个很长寿。这意味着会话cookie不会长时间更改。因此,如果有人设法以某种方式访问会话,他们将有很长的机会滥用对其他人的系统访问权限。 Identity通过旋转cookie来解决此问题 - 默认情况下,每隔30分钟更改一次auth cookie值。所以,如果你昨天获得某人的cookie价值 - 它就不会有任何好处。您还可以将此值减少到几分钟,甚至可以在每次请求时更新cookie值。
然后,您需要考虑会话到期和管理。首先,这将是一个内存耗尽 - 对于在过去30天内登录的每个用户,您必须在服务器上维护一个实时会话。想象一下,有一千个用户登录...我不知道每个用户会话有多少数据,但如果用得足够多,你就会开始遇到内存问题。然后,如果您想要对服务器进行负载平衡,则必须引入粘性会话。此外,当您的服务器重新启动时,您的所有用户都将失去他们的会话(我已经使用过这种系统 - 这很糟糕)。
接下来你需要处理多个用户登录 - 当同一个用户从2个不同的浏览器登录时会发生什么?用户更改密码时用户会话会发生什么 - 它如何注销其他浏览器?
我没有完成会话的大量工作,所以我不确定如何创建会话cookie。但是查看documentation (Session Identifiers section) sessionId存储在cookie中。并且您建议将User.Id放入该会话cookie中。 这意味着如果攻击者知道User.Id
,那么他们可以随时以该用户身份登录。为了减轻您的需求,您必须提出方法在会话中隐藏用户ID并使用某种相关ID,即使这样,你也无法逃避这样一个事实:一旦创建了相关id,它将持续整个会话时间--30天。谈论复杂的解决方案?
Identity为您提供了大量开箱即用的功能。你可能现在不需要的东西,但将来可能需要的东西。对于自行开发的解决方案,这将是一个自己编写的案例。
列表并非详尽无遗 - 只是我头脑中的一些东西。