这是在MVC 4中支持的默认AccountController中更改密码的代码:
// ChangePassword will throw an exception rather
//than return false in certain failure scenarios.
bool changePasswordSucceeded;
try
{
string userName = User.Identity.Name;
changePasswordSucceeded = WebSecurity.ChangePassword(userName,
model.OldPassword,
model.NewPassword);
}
catch (Exception)
{
changePasswordSucceeded = false;
}
if (changePasswordSucceeded)
{
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
ModelState.AddModelError("",
"The current password is incorrect or the new password is invalid.");
}
我的问题是该消息不清楚。如果当前密码不正确那么没关系,但如果新密码无效,我想向用户提供更好的消息,告诉他们出了什么问题,我想更好地理解“失败情景”,以便我可以定制消息。
文档here是关于例外的具体信息,我认为不应该在行动中吞下这些例外并将其报告为无效密码。
那么为什么这里有“新密码无效”的可能性呢?如果我在我的应用程序中仅使用没有OAuth的SimpleMembershipProvider,我可以将其删除吗?
编辑:NB此数据注释也出现在“RegisterModel”类中,因此此处也有密码有效性检查
[StringLength(100,
ErrorMessage = "The {0} must be at least {2} characters long.",
MinimumLength = 6)]
答案 0 :(得分:5)
这是一个很长的答案,所以我把它编辑成了几个部分。与像rook这样的用户相比,我不是安全专家,甚至他说不相信他的安全答案,或其他任何人。总是自己测试和理解它。任何阅读此内容的网络开发者都应该阅读the OWASP top ten web security flaws,使用Trustworthy Computing等在线指导,当然还有Mr. Bruce Schneier。对于我们任何人来说,安全性都很复杂且太大,因此请尽可能使用根据最佳实践进行工作的框架。最重要的是,全部保持in perspective。
有关这些摘要答案的更多详细信息,请参见下文:
从安全角度考虑:
机器告诉我
"当前密码不正确"
现在我再次尝试使用我认为您当前的密码:
"新密码无效"
我现在知道你的密码,但你不知道我做了什么,因为我没有改变任何东西。
脚注:我得到第一组逻辑错误,删除它,编辑并重新发布,但是嘿 - I'm not Bruce
这种攻击有很多组合,但它就像从糟糕的登录系统中收集电子邮件一样。想想如果我在尝试“恢复密码”时收到两条不同的消息会发生什么?使用电子邮件地址:
然后,我可以轻松找到您网站上的有效会员电子邮件,以便针对该用户进行有针对性的网上诱骗攻击,或者只是为垃圾邮件构建有效的电子邮件地址列表。
在两种情况下,我们更改密码的用户友好且同样安全的错误消息是:
"当前密码不正确或新密码无效。请记住,您的密码区分大小写,新密码必须包含[64 letters/5 numbers/4 characters / 3个希腊神的名字]"
为了保持理智,请将其保留在您的应用程序使用环境中,但请记住,您有责任使用更大的生态系统,users share passwords between websites,无论您是否喜欢。
关于ChangePassword何时返回false的问题部分:
基本上WebSecurity.ChangePassword
:
总之,如果符合以下情况,它会返回false
UserId
;或changePasswordSucceeded = false
。)newPassword
ChangePassword
有效性检查
醇>
所以从理论上讲,如果你的验证属性正确,忽略边缘情况,如果我们有边缘情况(用户已被删除,在Get和Post之间,则只能return false
,或者我们无法访问数据库,或者当前密码无效)。
即使在攻击者绕过浏览器中的UI(他们将会绕过),因为Action本身在模型上调用IsValid
,这一切都是正确的。
这里有一个严肃的免责声明:我不会在安全上花费我的生命。我遵循安全设计原则(例如,我跟上the OWASP top ten project),并相信我对最重要的安全原则有很好的认识。因此,我可能有一些错误。
如果客户端"密码要求"验证不存在 - 会发生什么?用户必须等待Post返回才能找出发生的事情。
如果客户端"密码要求"验证是那里,它会削弱我们的界面吗?我不相信。:
MVC并不是AFAIK做这些事情中的任何一个,所以这就是它开始崩溃的地方。
它也因为操作中的Model.IsValid
测试而从服务器返回不同的错误和消息而分崩离析,该测试强制执行新的密码验证以及针对此失败的不同错误消息。因此,在其当前实现中,单个错误消息方法存在缺陷。
那么我会改变这一切的方式吗?希望我及时改进其他部分,除了将返回消息更改为更长一些且信息更丰富之外,我可能不会这样做。
这是个人意见,可以反过来论证
细节:
Membership.GetUser(userName, true).ChangePassword(...)
。如果是ArgumentException see docs,它将返回false
。ChangePassword
(例如SimpleMembershipProvider.ChangePassword
),如果失败则返回false
。 实际的提供程序实现变得复杂。例如,对于SimpleMembershipProvider
,
ArgumentExceptions
(冒泡到catch
中的return false
和MembershipUser.ChangePassword
)。 UserId
(如果失败则返回false),PasswordChangedDate
MembershipUser