基于表单的网站身份验证的权威指南

Michiel de Mare 5154 language-agnostic security authentication article http

基于表单的网站身份验证

我们认为Stack Overflow不仅应该是非常具体的技术问题的资源,而且还应该是关于如何解决常见问题变化的一般指导原则."基于表单的网站身份验证"应该是这种实验的一个很好的主题.

它应包括以下主题:

  • 如何登录
  • 如何退出
  • 如何保持登录状态
  • 管理cookie(包括推荐设置)
  • SSL/HTTPS加密
  • 如何存储密码
  • 使用秘密问题
  • 忘记用户名/密码功能
  • 使用nonce来防止跨站点请求伪造(CSRF)
  • OpenID的
  • "记住我"复选框
  • 浏览器自动完成用户名和密码
  • 秘密URL(受摘要保护的公共URL)
  • 检查密码强度
  • 电子邮件验证
  • 还有更多关于 基于表单的身份验证 ...

它不应该包括以下内容:

  • 角色和授权
  • HTTP基本身份验证

请帮助我们:

  1. 建议子主题
  2. 提交有关此主题的好文章
  3. 编辑官方答案

Jens Roland.. 3602

第一部分:如何登录

我们假设您已经知道如何构建登录+密码HTML表单,该表单将值POST到服务器端的脚本以进行身份​​验证.下面的部分将讨论声音实用auth的模式,以及如何避免最常见的安全陷阱.

HTTPS还是HTTPS?

除非连接已经安全(即通过HTTPS使用SSL/TLS进行隧道传输),否则您的登录表单值将以明文形式发送,这允许任何窃听浏览器和Web服务器之间的线路的人都可以在通过时读取登录信息通过.这类窃听是由政府定期完成的,但总的来说,除了这样说之外,我们不会解决"拥有"的电话:如果您要保护任何重要信息,请使用HTTPS.

实质上,在登录期间防止窃听/数据包嗅探的唯一实用方法是使用HTTPS或其他基于证书的加密方案(例如,TLS)或经过验证和测试的质询 - 响应方案(例如,Diffie-Hellman)基于SRP).窃听攻击者可以轻易绕过任何其他方法.

当然,如果你愿意有点不切实际,你也可以采用某种形式的双因素认证方案(例如Google Authenticator应用程序,物理'冷战风格'代码簿或RSA密钥生成器加密狗).如果应用正确,即使使用不安全的连接,这也可以工作,但是很难想象开发人员愿意实现双因素身份验证而不是SSL.

(不)滚动自己的JavaScript加密/散列

考虑到在您的网站上设置SSL证书的非零成本和感知技术难度,一些开发人员倾向于推出他们自己的浏览器内哈希或加密方案,以避免通过不安全的线路传递明文登录.

虽然这是一个崇高的想法,但它基本上是无用的(并且可能是一个安全漏洞),除非它与上述之一相结合 - 也就是说,要么使用强加密来保护线路,要么使用久经考验的挑战 - 响应机制(如果你不知道那是什么,只要知道它是最难以证明的,最难设计的,也是最难实现的数字安全概念).

虽然散列密码可以有效防止密码泄露,但它很容易受到重放攻击,中间人攻击/劫持(如果攻击者可以在你的不安全的HTML页面到达你的之前注入几个字节)浏览器,他们可以简单地注释掉JavaScript中的哈希),或者暴力攻击(因为你正在向攻击者发送用户名,盐和哈希密码).

CAPTCHAS反人类

CAPTCHA旨在挫败一种特定类型的攻击:自动字典/强力试错,没有人类操作员.毫无疑问,这是一个真正的威胁,但是,有一些方法可以无缝地处理它,不需要CAPTCHA,特别是正确设计的服务器端登录限制方案 - 我们稍后会讨论它们.

知道CAPTCHA实现不是一样的; 它们通常不是人类可以解决的,其中大多数实际上对机器人无效,所有这些都对廉价的第三世界劳动力无效(根据OWASP,目前的血汗工厂率为每500次测试12美元),并且一些实施可能是在某些国家/地区技术上非法(请参阅OWASP身份验证备忘单).如果您必须使用CAPTCHA,请使用Google的reCAPTCHA,因为它定义为OCR-hard(因为它使用已经过OCR错误分类的书籍扫描)并且非常努力地使用户友好.

就个人而言,我倾向于发现CAPTCHAS很烦人,并且当用户多次登录失败并且节流延迟最大化时,仅将其用作最后的手段.这种情况很少发生,可以接受,并且整个系统都得到了加强.

存储密码/验证登录

在我们近年来看到的所有高度公开的黑客攻击和用户数据泄漏之后,这可能最终是常识,但必须说明:不要在数据库中以明文形式存储密码.用户数据库通常会通过SQL注入被黑客入侵,泄露或收集,如果您要存储原始明文密码,那么即时游戏结束也是为了您的登录安全性.

因此,如果您无法存储密码,如何检查登录表单中登录的登录名+密码组合是否正确?答案是使用密钥派生函数进行散列.无论何时创建新用户或更改密码,您都会获取密码并通过KDF运行,例如Argon2,bcrypt,scrypt或PBKDF2,将明文密码("correcthorsebatterystaple")转换为长而随机的字符串,这在您的数据库中存储更安全.要验证登录,请对输入的密码运行相同的哈希函数,这次传入salt并将生成的哈希字符串与存储在数据库中的值进行比较.Argon2,bcrypt和scrypt已经将哈希值与哈希一起存储.有关更多详细信息,请参阅sec.stackexchange上的这篇文章.

使用salt的原因是散列本身是不够的 - 你需要添加一个所谓的'salt'来保护散列不受彩虹表的影响.salt有效地防止两个完全匹配的密码被存储为相同的哈希值,从而防止在攻击者正在执行密码猜测攻击时在一次运行中扫描整个数据库.

加密哈希不应该用于密码存储,因为用户选择的密码不够强(即通常不包含足够的熵),并且密码猜测攻击可以在相对较短的时间内由访问哈希的攻击者完成.这就是使用KDF的原因 - 这些有效地"拉伸了密钥",这意味着攻击者所做的每个密码都会导致哈希算法的多次重复,例如10,000次,这会导致攻击者将密码猜测速度减慢10,000倍.

会话数据 - "您以Spiderman69身份登录"

一旦服务器针对您的用户数据库验证了登录名和密码并找到匹配项,系统就需要一种方法来记住浏览器已经过身份验证.这个事实应该只在服务器端存储在会话数据中.

如果您不熟悉会话数据,可以使用以下方法:单个随机生成的字符串存储在过期的cookie中,用于引用存储在服务器上的数据集合 - 会话数据.如果您使用的是MVC框架,那么这无疑已经得到了处理.

如果可能,请确保会话cookie在发送到浏览器时设置了安全且仅HTTP标记.HttpOnly标志提供一些保护,防止通过XSS攻击读取cookie.安全标志确保cookie仅通过HTTPS发回,因此可防止网络嗅探攻击.cookie的值不应该是可预测的.如果呈现引用不存在的会话的cookie,则应立即替换其值以防止会话固定.

第二部分:如何保持登录 - 臭名昭着的"记住我"复选框

持久登录Cookie("记住我"功能)是一个危险区域; 一方面,当用户了解如何处理它们时,它们与传统登录完全一样安全; 而另一方面,它们在粗心用户手中是一个巨大的安全风险,他们可能在公共计算机上使用它们而忘记注销,并且可能不知道浏览器cookie是什么或如何删除它们.

Personally, I like persistent logins for the websites I visit on a regular basis, but I know how to handle them safely. If you are positive that your users know the same, you can use persistent logins with a clean conscience. If not - well, then you may subscribe to the philosophy that users who are careless with their login credentials brought it upon themselves if they get hacked. It's not like we go to our user's houses and tear off all those facepalm-inducing Post-It notes with passwords they have lined up on the edge of their monitors, either.

Of course, some systems can't afford to have any accounts hacked; for such systems, there is no way you can justify having persistent logins.

If you DO decide to implement persistent login cookies, this is how you do it:

  1. First, take some time to read Paragon Initiative's article on the subject. You'll need to get a bunch of elements right, and the article does a great job of explaining each.

  2. And just to reiterate one of the most common pitfalls, DO NOT STORE THE PERSISTENT LOGIN COOKIE (TOKEN) IN YOUR DATABASE, ONLY A HASH OF IT! The login token is Password Equivalent, so if an attacker got their hands on your database, they could use the tokens to log in to any account, just as if they were cleartext login-password combinations. Therefore, use hashing (according to https://security.stackexchange.com/a/63438/5002 a weak hash will do just fine for this purpose) when storing persistent login tokens.

PART III: Using Secret Questions

Don't implement 'secret questions'. The 'secret questions' feature is a security anti-pattern. Read the paper from link number 4 from the MUST-READ list. You can ask Sarah Palin about that one, after her Yahoo! email account got hacked during a previous presidential campaign because the answer to her security question was... "Wasilla High School"!

Even with user-specified questions, it is highly likely that most users will choose either:

  • A 'standard' secret question like mother's maiden name or favorite pet

  • A simple piece of trivia that anyone could lift from their blog, LinkedIn profile, or similar

  • Any question that is easier to answer than guessing their password. Which, for any decent password, is every question you can imagine

In conclusion, security questions are inherently insecure in virtually all their forms and variations, and should not be employed in an authentication scheme for any reason.

The true reason why security questions even exist in the wild is that they conveniently save the cost of a few support calls from users who can't access their email to get to a reactivation code. This at the expense of security and Sarah Palin's reputation. Worth it? Probably not.

PART IV: Forgotten Password Functionality

I already mentioned why you should never use security questions for handling forgotten/lost user passwords; it also goes without saying that you should never e-mail users their actual passwords. There are at least two more all-too-common pitfalls to avoid in this field:

  1. Don't reset a forgotten password to an autogenerated strong password - such passwords are notoriously hard to remember, which means the user must either change it or write it down - say, on a bright yellow Post-It on the edge of their monitor. Instead of setting a new password, just let users pick a new one right away - which is what they want to do anyway. (An exception to this might be if the users are universally using a password manager to store/manage passwords that would normally be impossible to remember without writing it down).

  2. Always hash the lost password code/token in the database. AGAIN, this code is another example of a Password Equivalent, so it MUST be hashed in case an attacker got their hands on your database. When a lost password code is requested, send the plaintext code to the user's email address, then hash it, save the hash in your database -- and throw away the original. Just like a password or a persistent login token.

A final note: always make sure your interface for entering the 'lost password code' is at least as secure as your login form itself, or an attacker will simply use this to gain access instead. Making sure you generate very long 'lost password codes' (for example, 16 case-sensitive alphanumeric characters) is a good start, but consider adding the same throttling scheme that you do for the login form itself.

PART V: Checking Password Strength

First, you'll want to read this small article for a reality check: The 500 most common passwords

Okay, so maybe the list isn't the canonical list of most common passwords on any system anywhere ever, but it's a good indication of how poorly people will choose their passwords when there is no enforced policy in place. Plus, the list looks frighteningly close to home when you compare it to publicly available analyses of recently stolen passwords.

So: With no minimum password strength requirements, 2% of users use one of the top 20 most common passwords. Meaning: if an attacker gets just 20 attempts, 1 in 50 accounts on your website will be crackable.

Thwarting this requires calculating the entropy of a password and then applying a threshold. The National Institute of Standards and Technology (NIST) Special Publication 800-63 has a set of very good suggestions. That, when combined with a dictionary and keyboard layout analysis (for example, 'qwertyuiop' is a bad password), can reject 99% of all poorly selected passwords at a level of 18 bits of entropy. Simply calculating password strength and showing a visual strength meter to a user is good, but insufficient. Unless it is enforced, a lot of users will most likely ignore it.

And for a refreshing take on user-friendliness of high-entropy passwords, Randall Munroe's Password Strength xkcd is highly recommended.

PART VI: Much More - Or: Preventing Rapid-Fire Login Attempts

First, have a look at the numbers: Password Recovery Speeds - How long will your password stand up

If you don't have the time to look through the tables in that link, here's the list of them:

  1. It takes virtually no time to crack a weak password, even if you're cracking it with an abacus

  2. It takes virtually no time to crack an alphanumeric 9-character password if it is case insensitive

  3. It takes virtually no time to crack an intricate, symbols-and-letters-and-numbers, upper-and-lowercase password if it is less than 8 characters long (a desktop PC can search the entire keyspace up to 7 characters in a matter of days or even hours)

  4. It would, however, take an inordinate amount of time to crack even a 6-character password, if you were limited to one attempt per second!

So what can we learn from these numbers? Well, lots, but we can focus on the most important part: the fact that preventing large numbers of rapid-fire successive login attempts (ie. the brute force attack) really isn't that difficult. But preventing it right isn't as easy as it seems.

Generally speaking, you have three choices that are all effective against brute-force attacks (and dictionary attacks, but since you are already employing a strong passwords policy, they shouldn't be an issue):

  • Present a CAPTCHA after N failed attempts (annoying as hell and often ineffective -- but I'm repeating myself here)

  • Locking accounts and requiring email verification after N failed attempts (this is a DoS attack waiting to happen)

  • And finally, login throttling: that is, setting a time delay between attempts after N failed attempts (yes, DoS attacks are still possible, but at least they are far less likely and a lot more complicated to pull off).

Best practice #1: A short time delay that increases with the number of failed attempts, like:

  • 1 failed attempt = no delay
  • 2 failed attempts = 2 sec delay
  • 3 failed attempts = 4 sec delay
  • 4 failed attempts = 8 sec delay
  • 5 failed attempts = 16 sec delay
  • etc.

DoS attacking this scheme would be very impractical, since the resulting lockout time is slightly larger than the sum of the previous lockout times.

To clarify: The delay is not a delay before returning the response to the browser. It is more like a timeout or refractory period during which login attempts to a specific account or from a specific IP address will not be accepted or evaluated at all. That is, correct credentials will not return in a successful login, and incorrect credentials will not trigger a delay increase.

Best practice #2: A medium length time delay that goes into effect after N failed attempts, like:

  • 1-4 failed attempts = no delay
  • 5 failed attempts = 15-30 min delay

DoS attacking this scheme would be quite impractical, but certainly doable. Also, it might be relevant to note that such a long delay can be very annoying for a legitimate user. Forgetful users will dislike you.

Best practice #3: Combining the two approaches - either a fixed, short time delay that goes into effect after N failed attempts, like:

  • 1-4 failed attempts = no delay
  • 5+ failed attempts = 20 sec delay

Or, an increasing delay with a fixed upper bound, like:

  • 1 failed attempt = 5 sec delay
  • 2 failed attempts = 15 sec delay
  • 3+ failed attempts = 45 sec delay

This final scheme was taken from the OWASP best-practices suggestions (link 1 from the MUST-READ list) and should be considered best practice, even if it is admittedly on the restrictive side.

As a rule of thumb, however, I would say: the stronger your password policy is, the less you have to bug users with delays. If you require strong (case-sensitive alphanumerics + required numbers and symbols) 9+ character passwords, you could give the users 2-4 non-delayed password attempts before activating the throttling.

DoS attacking this final login throttling scheme would be very impractical. And as a final touch, always allow persistent (cookie) logins (and/or a CAPTCHA-verified login form) to pass through, so legitimate users won't even be delayed while the attack is in progress. That way, the very impractical DoS attack becomes an extremely impractical attack.

Additionally, it makes sense to do more aggressive throttling on admin accounts, since those are the most attractive entry points

PART VII: Distributed Brute Force Attacks

Just as an aside, more advanced attackers will try to circumvent login throttling by 'spreading their activities':

  • Distributing the attempts on a botnet to prevent IP address flagging

  • Rather than picking one user and trying the 50.000 most common passwords (which they can't, because of our throttling), they will pick THE most common password and try it against 50.000 users instead. That way, not only do they get around maximum-attempts measures like CAPTCHAs and login throttling, their chance of success increases as well, since the number 1 most common password is far more likely than number 49.995

  • Spacing the login requests for each user account, say, 30 seconds apart, to sneak under the radar

Here, the best practice would be logging the number of failed logins, system-wide, and using a running average of your site's bad-login frequency as the basis for an upper limit that you then impose on all users.

Too abstract? Let me rephrase:

Say your site has had an average of 120 bad logins per day over the past 3 months. Using that (running average), your system might set the global limit to 3 times that -- ie. 360 failed attempts over a 24 hour period. Then, if the total number of failed attempts across all accounts exceeds that number within one day (or even better, monitor the rate of acceleration and trigger on a calculated threshold), it activates system-wide login throttling - meaning short delays for ALL users (still, with the exception of cookie logins and/or backup CAPTCHA logins).

I also posted a question with more details and a really good discussion of how to avoid tricky pitfals in fending off distributed brute force attacks

PART VIII: Two-Factor Authentication and Authentication Providers

Credentials can be compromised, whether by exploits, passwords being written down and lost, laptops with keys being stolen, or users entering logins into phishing sites. Logins can be further protected with two-factor authentication, which uses out-of-band factors such as single-use codes received from a phone call, SMS message, app, or dongle. Several providers offer two-factor authentication services.

Authentication can be completely delegated to a single-sign-on service, where another provider handles collecting credentials. This pushes the problem to a trusted third party. Google and Twitter both provide standards-based SSO services, while Facebook provides a similar proprietary solution.

MUST-READ LINKS About Web Authentication

  1. OWASP Guide To Authentication/OWASP Authentication Cheat Sheet
  2. Dos and Don’ts of Client Authentication on the Web (very readable MIT research paper)
  3. Wikipedia: HTTP cookie
  4. Personal knowledge questions for fallback authentication: Security questions in the era of Facebook (very readable Berkeley research paper)

  • @Jeff:很遗憾听到你的回复有问题.我不知道关于这个答案有关于Meta的争论,如果你问我,我会很乐意自己编辑.删除我的帖子只是从我的帐户中删除了1200声誉,这会伤害:( (222认同)
  • 嗯,我真的不同意Captcha部分,是的,Captchas很烦人,它们可以被破坏(除了recaptcha,但这几乎是人类无法解决的!)但这就像是说不要使用垃圾邮件过滤器,因为它有误报率低于0.1%..这个网站使用的是Captchas,它们并不完美,但它们会减少相当数量的垃圾邮件,而且根本就没有好的替代品 (61认同)
  • "在发送身份验证令牌之后,系统需要一种方法来记住您已经过身份验证 - 这个事实应该只存储在会话数据中的服务器端.可以使用cookie来引用会话数据." 不完全的.您可以(并且应该为无状态服务器!)使用加密签名的cookie.这是不可能伪造的,不会占用服务器资源,也不需要粘性会话或其他恶作剧. (13认同)
  • "台式电脑可以在不到90天的时间内搜索FULL KEYSPACE最多7个字符"具有最新GPU的机器可以在不到1天的时间内搜索完整的7个字符键空间.顶级GPU可以每秒管理10亿个哈希值.http://www.golubev.com/hashgpu.htm这导致了一些关于密码存储的结论,这些结论没有直接解决. (12认同)
  • 我很惊讶没有提到CSRF保护...... (9认同)
  • @MikeMike:"..并在php中循环它们" - 为什么不在SQL中选择行?`SELECT*FROM LoginTokens WHERE UserID = [来自cookie的用户ID]和HashedToken = [hash(来自cookie的令牌)]`应该工作正常(记得为SQL使用预准备语句/存储过程) (6认同)
  • 用于持久登录.Username + token如何比服务器映射到用户名和loginstatus的随机session-id更好?我以前从未听说过第一种方法. (5认同)
  • 这里有一些事情要么简要提及,要么根本不提.一种是使用特定于密码的散列算法(例如bcrypt).这意味着计算哈希值的时间增加到0.1秒(至少),但在搜索整个键空间时会产生很大的差异.第二件事是安全必须无处不在:对用户输入进行sanatizing,使用sql的预准备语句,确保资源不可预测,然后有整个XSS问题集...... (5认同)
  • 我完全同意你的安全问题.他们非常糟糕.我只是希望能向银行解释一下. (4认同)
  • 这是我在Stack Overflow上见过的最长,最有趣的答案.但它真的更适合博客文章! (3认同)
  • @Sidnicious:那你不是在讨论会话cookie.根据定义,会话cookie没有expires指令.如果将expires指令添加到会话cookie,它将成为持久cookie.听起来你想让你的"会话"cookie持久化并消除真正的会话限制cookie.我想这是可能的,但你失去了你可以用会话cookie做的所有有用的东西,即在内存中保存瞬态轻量级状态对象(你不想让所有的会话数据保持数月,请相信我). (3认同)
  • 同意@chacham15.锁定和限制策略很棒,但使用像bcrypt或scrypt这样的*password*摘要而不是通用散列函数可以在尽可能最低的级别强制执行此操作.没有必要花费全部工作来生成密码摘要,因此没有开发人员可以简单地忘记实现或意外地禁用限制机制. (3认同)
  • @aero:通过在持久登录cookie令牌中包含用户名,可以避免攻击者有1000万次猜测正确令牌的情况(在拥有1000万用户的站点上).当然,如果令牌字符串足够长,它应该不是一个大问题,但我仍然会推荐它. (2认同)

Michiel de M.. 403

最终文章

发送凭据

100%安全地发送凭证的唯一实用方法是使用SSL.使用JavaScript来散列密码是不安全的.客户端密码散列的常见缺陷:

  • 如果客户端和服务器之间的连接未加密,那么您所做的一切都很容易受到中间人攻击.攻击者可以替换传入的javascript以打破散列或将所有凭据发送到他们的服务器,他们可以听取客户端响应并完美地模仿用户等等.具有可信证书颁发机构的SSL旨在防止MitM攻击.
  • 如果您不在服务器上执行其他冗余工作,则服务器收到的散列密码安全性较低.

还有另一种称为SRP的安全方法,但它已获得专利(虽然它是免费许可的),但很少有好的实现可用.

存储密码

不要将密码作为纯文本存储在数据库中.即使您不关心自己网站的安全性也不会.假设您的某些用户将重复使用其在线银行帐户的密码.因此,存储散列密码,并丢弃原始密码.并确保密码不会显示在访问日志或应用程序日志中.OWASP 建议使用Argon2作为新应用的首选.如果没有,则应使用PBKDF2或scrypt.最后,如果以上都不可用,请使用bcrypt.

哈希本身也是不安全的.例如,相同的密码意味着相同的哈希 - 这使得哈希查找表成为一次破解大量密码的有效方法.相反,存储盐渍哈希.salt是在散列之前附加到密码的字符串 - 每个用户使用不同的(随机)salt.salt是一个公共值,因此您可以将哈希值存储在数据库中.有关详细信息,请参见此处.

这意味着您无法向用户发送他们忘记的密码(因为您只有哈希).除非您已对用户进行身份验证,否则不要重置用户的密码(用户必须证明他们能够阅读发送到存储(和验证的)电子邮件地址的电子邮件.)

安全问题

安全问题是不安全的 - 避免使用它们.为什么?安全问题,密码做得更好.阅读第三部分:@Jens Roland中使用秘密问题在这个维基中回答.

会话cookie

用户登录后,服务器会向用户发送会话cookie.服务器可以从cookie中检索用户名或id,但是没有其他人可以生成这样的cookie(TODO解释机制).

Cookie可能被劫持:它们只能与客户机器的其他部分和其他通信一样安全.它们可以从磁盘读取,在网络流量中嗅探,由跨站点脚本攻击解除,从中毒的DNS中删除,以便客户端将其cookie发送到错误的服务器.不要发送持久性cookie.Cookie应在客户端会话结束时到期(浏览器关闭或离开您的域).

如果要对用户进行自动登录,可以设置持久性cookie,但它应与完整会话cookie不同.您可以设置用户已自动登录的附加标志,并且需要登录才能进行敏感操作.这对于希望为您提供无缝,个性化购物体验但仍能保护您的财务详细信息的购物网站而言非常受欢迎.例如,当您返回访问亚马逊时,他们会向您显示一个看起来像您已登录的页面,但当您下订单(或更改您的送货地址,信用卡等)时,他们会要求您确认你的密码.

另一方面,银行和信用卡等金融网站只有敏感数据,不允许自动登录或低安全模式.

外部资源清单


Charlie.. 154

首先,一个强烈的警告,这个答案不是最适合这个问题的答案.绝对不应该是最好的答案!

我将继续提及Mozilla提出的BrowserID(或者更确切地说,可能更确切地说,已验证的电子邮件协议),其目的是寻找未来更好的身份验证方法的升级途径.

我将这样总结一下:

  1. Mozilla是一个非盈利组织,其价值与找到解决此问题的良好解决方案非常吻合.
  2. 今天的现实是大多数网站使用基于表单的身份验证
  3. 基于表单的身份验证有一个很大的缺点,即增加了网络钓鱼的风险.要求用户将敏感信息输入到由远程实体控制的区域,而不是由其用户代理(浏览器)控制的区域.
  4. 由于浏览器是隐式信任的(用户代理的整个想法是代表用户行事),因此它们可以帮助改善这种情况.
  5. 这里阻碍进展的主要力量是部署僵局.必须将解决方案分解为自己提供一些增量收益的步骤.
  6. 用于表达内置于互联网基础设施中的身份的最简单的分散方法是域名.
  7. 作为表达身份的第二级,每个域管理自己的一组帐户.
  8. "帐户@域"形式简洁明了,并受到各种协议和URI方案的支持.当然,这种标识符最普遍地被认为是电子邮件地址.
  9. 电子邮件提供商已经是在线事实上的主要身份提供商.如果您可以证明您控制该帐户的相关电子邮件地址,则当前的密码重置流程通常可让您控制帐户.
  10. 建议使用经过验证的电子邮件协议,以提供基于公钥加密的安全方法,以简化在域A上拥有帐户的域B的过程.
  11. 对于不支持已验证电子邮件协议的浏览器(目前全部都是这样),Mozilla提供了一个在客户端JavaScript代码中实现协议的垫片.
  12. 对于不支持已验证电子邮件协议的电子邮件服务,该协议允许第三方充当可信中间人,断言他们已验证用户对帐户的所有权.拥有大量此类第三方是不可取的; 此功能仅用于允许升级路径,并且更优选的是电子邮件服务本身提供这些断言.
  13. Mozilla提供自己的服务,就像这样一个值得信赖的第三方.实施验证电子邮件协议的服务提供商(即依赖方)可能会选择信任Mozilla的断言.Mozilla的服务使用传统方式发送带有确认链接的电子邮件来验证用户的帐户所有权.
  14. 当然,除了他们可能希望提供的任何其他身份验证方法之外,服务提供商还可以提供此协议作为选项.
  15. 这里寻求的大用户界面好处是"身份选择器".当用户访问网站并选择进行身份验证时,他们的浏览器会向他们显示他们可能用来向网站标识自己的电子邮件地址("个人","工作","政治激进主义"等).
  16. 作为这项工作的一部分,正在寻求的另一个重大用户界面优势是帮助浏览器更多地了解用户的会话 - 他们当前主要登录的是谁 - 因此它可能会在浏览器chrome中显示.
  17. 由于该系统的分布式特性,它避免了对Facebook,Twitter,Google等主要网站的锁定.任何个人都可以拥有自己的域,因此可以充当自己的身份提供者.

这不是严格的"基于表单的网站身份验证".但是,努力从基于表单的身份验证的当前规范过渡到更安全的东西:浏览器支持的身份验证.


Pieter888.. 127

我只是觉得我会分享这个我发现工作得很好的解决方案.

我称之为Dummy Field(虽然我没有发明这个,所以不要相信我).

简而言之:您只需将其插入到您的<form>身份并在验证时检查它是否为空:

<input type="text" name="email" style="display:none" />

诀窍是欺骗机器人认为必须将数据插入必填字段,这就是为什么我将输入命名为"电子邮件".如果您已经有一个名为email的字段,那么您应该尝试将虚拟字段命名为"company","phone"或"emailaddress".只需选择一些您不需要的东西,以及人们通常认为可以填写到网络表单中的东西.现在input使用CSS或JavaScript/jQuery 隐藏字段 - 无论什么最适合你 - 只是不要设置输入type,hidden否则机器人不会为此而堕落.

当您验证表单(客户端或服务器端)时,检查您的虚拟字段是否已填满,以确定它是由人还是机器人发送的.

例:

如果是人: 用户将看不到虚拟字段(在我的情况下命名为"email")并且不会尝试填充它.因此,在发送表单时,虚拟字段的值仍应为空.

在机器人的情况下:机器人将看到一个字段,其类型是text和一个名称email(或你称之为它的任何名称),并将逻辑上尝试用适当的数据填充它.如果您使用一些花哨的CSS设置输入表单的样式并不关心,Web开发人员会一直这样做.无论虚拟场中的值是什么,只要它比0字符大,我们就不在乎.

我在留言簿上使用这种方法与CAPTCHA结合使用,之后我没有看过任何一封垃圾邮件帖子.我之前使用过CAPTCHA解决方案,但最终每小时产生了大约5个垃圾邮件.在表单中添加虚拟字段已停止(至少到现在为止)所有垃圾邮件都会出现.

我相信这也可以用于登录/身份验证表单.

警告:当然这种方法并非100%万无一失.可以将机器人编程为忽略display:none应用了样式的输入字段.您还必须考虑使用某种形式的自动完成功能的人(比如大多数浏览器都内置了!)来自动填充所有表单字段.他们可能也会选择一个虚拟场.

您也可以通过让虚拟区域可见但在屏幕边界之外可以稍微改变一下,但这完全取决于您.

要有创意!

  • 这是一个有用的反垃圾邮件技巧,但我建议使用"电子邮件"以外的字段名称,否则您可能会发现浏览器自动填充它,无意中阻止了您网站的真正用户. (29认同)
  • 无需内联样式.只需在字段中添加一个类(可能使用一个对机器人来说永远不会有任何意义的奇怪单词),并通过网站的CSS文件隐藏它.比如:`<input type ="text"name ="email"class ="cucaracha">`和你的CSS:`.cucaracha {display:none; }`. (24认同)
  • 当视力受损的用户使用屏幕阅读器导航表格时会发生什么? (17认同)
  • 我还有几个使用`visibility:hidden`和`position:absolute; top:-9000px`你也可以对其中的一些元素执行`text-indent`和`z-index`并放置它们在具有尴尬名称的压缩CSS文件名中 - 因为机器人可以检测到1display:none`并且它们现在检查一系列组合 - 我实际上使用这些方法并且它们是交易的旧技巧.+1 (6认同)
  • 这种技术有一个名称:蜜罐http://en.wikipedia.org/wiki/Honeypot_(computing) (6认同)
  • Aww,我有一天想出了这个,正如你所提到的,一旦我将它应用到我在多个网站上的联系表单,它已经绝对阻止垃圾邮件超过一年.喜欢它,但是当我在一个高知名度的网站上看到它时,我很害怕.;) (2认同)
  • 我想在这里提到潜在的可访问性问题.您应该包含一个消息(也可以隐藏),该字段应留空. (2认同)

you cad sir .. 75

我不认为上述答案是"错误的",但有大量的认证没有涉及(或者更重要的是"如何实现cookie会话",而不是"有哪些选项可用,什么是交易" -offs".

我建议的编辑/答案是

  • 问题在于帐户设置比在密码检查中更多.
  • 使用双因素身份验证比更聪明的密码加密方法更安全
  • 不要尝试实现自己的密码登录表单或数据库存储,除非在创建帐户和自行生成时存储的数据是无价值的(即Facebook,Flickr等Web 2.0样式)

    1. 摘要式身份验证是一种基于标准的方法,支持所有主流浏览器和服务器,即使通过安全通道也不会发送密码.

这避免了任何需要"会话"或cookie的需要,因为浏览器本身每次都会重新加密通信.它是最"轻量级"的开发方法.

但是,除了公共的低价值服务之外,我不建议这样做.这是上面一些其他答案的问题 - 不要尝试重新实现服务器端身份验证机制 - 这个问题已经解决并且得到大多数主流浏览器的支持.不要使用cookies.不要在您自己的手工数据库中存储任何内容.根据请求,只询问请求是否经过身份验证.配置和第三方可信软件应支持其他所有功能.

所以......

首先,我们将初始创建帐户(带密码)与随后重新检查密码混淆.如果我是Flickr并且是第一次创建您的站点,则新用户可以访问零值(空白Web空间).如果创建帐户的人谎称他们的名字,我真的不在乎.如果我创建一个帐户医院联网/外联网的,价值在于所有的医疗记录,所以我关心帐户创建者的身份(*).

这是非常困难的部分.该唯一体面的解决办法是信任的网站.例如,您作为医生加入医院.您创建一个托管在您的照片,护照号码和公钥的某个地方的网页,并使用私钥对它们进行哈希处理.然后,您访问医院,系统管理员查看您的护照,查看照片是否与您匹配,然后使用医院私钥对网页/照片哈希进行哈希处理.从现在开始,我们可以安全地交换密钥和令牌.任何信任医院的人都可以(有秘密酱BTW).系统管理员还可以为您提供RSA加密狗或其他双因素身份验证.

但是,这是一个很多麻烦的,而不是非常的Web 2.0.但是,它是创建可以访问非自创的有价值信息的新帐户的唯一安全方法.

  1. Kerberos和SPNEGO - 具有可信第三方的单点登录机制 - 基本上用户验证可信第三方.(注意,这绝不是不值得信任的OAuth)

  2. SRP - 一种没有可信第三方的聪明密码身份验证.但在这里,我们进入了"使用双因素身份验证更安全的领域,即使这样更昂贵"

  3. SSL客户端 - 为客户端提供公钥证书(在所有主流浏览器中都支持 - 但会引发有关客户端计算机安全性的问题).

最后,这是一个权衡 - 安全漏洞的成本与实施更安全的方法的成本是什么.有一天,我们可能会看到一个广泛接受的正确PKI,因此不再有自己的滚动认证表单和数据库.一天...

  • 很难说出你在谈论的答案是"我不认为上述答案是"错误的" (25认同)

用户甲.. 51

散列时,不要使用快速哈希算法,如MD5(存在许多硬件实现).使用像SHA-512这样的东西.对于密码,较慢的哈希值更好.

创建哈希值的速度越快,任何暴力检查程序的工作速度就越快.因此较慢的哈希将减缓暴力迫使.慢速哈希算法会使更长时间的密码(8位+)变得不切实际

  • 说明:创建哈希值的速度越快,任何暴力检查程序的工作速度就越快.因此较慢的哈希将减缓暴力迫使.慢速哈希算法会使更长时间的密码(8位+)变得不切实际 (14认同)
  • SHA-512也很快,因此您需要进行数千次迭代. (4认同)
  • 更喜欢像bcrypt那样设计用于缓慢散列的东西. (4认同)
  • "不要使用快速哈希算法......慢速哈希更好" - 解释?文档? (3认同)
  • 正如另一个答案中所提到的,"OWASP建议使用Argon2作为新应用程序的首选.如果不可用,则应使用PBKDF2或scrypt.最后,如果以上都不可用,请使用bcrypt." MD5和任何SHA散列函数都不应该用于散列密码.这个答案是不好的建议. (2认同)

用户甲.. 50

关于实际密码强度估计的好文章是:

Dropbox Tech Blog»博客存档»zxcvbn:真实的密码强度估算


pixeline.. 45

关于身份验证系统我最喜欢的规则:使用密码而不是密码.容易记住,难以破解.更多信息:编码恐怖:密码与通行短语


Iain Duncan.. 21

我想根据防御深度添加一个我用过的建议.您不需要为常规用户提供与管理员相同的auth&auth系统.您可以在单独的URL上使用单独的登录表单,为要授予高权限的请求执行单独的代码.这个可以做出对普通用户来说完全痛苦的选择.我使用过的一种方法是实际加密管理员访问的登录URL,并通过电子邮件向管理员发送新的URL.立即停止任何暴力攻击,因为您的新URL可能是任意困难的(非常长的随机字符串),但您的管理员用户唯一的不便是在他们的电子邮件中跟踪链接.攻击者不再知道POST到哪里.


xyz.. 13

我不知道最好回答这个问题作为答案或评论.我选择了第一个选项.

关于第四部分:在第一个答案中忘记密码功能,我会指出时间攻击.

在" 记住您的密码"表单中,攻击者可能会检查完整的电子邮件列表并检测哪些已注册到系统(请参阅下面的链接).

关于遗忘密码表格,我想补充说,使用一些延迟功能在成功和不成功查询之间等于时间是个好主意.

https://crypto.stanford.edu/~dabo/papers/webtiming.pdf


Mike Robinso.. 12

我想补充一点非常重要的评论: -

  • "在公司 内部网络环境中,"如果不是所有上述内容都可能不适用!

许多公司部署"仅限内部使用"的网站,这些网站实际上是恰好通过URL实现的"公司应用程序".这些URL可以(据说......)仅在"公司内部网络"中解析.(哪个网络神奇地包括所有与VPN连接的"公路战士".)

当用户尽职地连接到上述网络时,他们的身份("身份验证") [已经......]最终知道,"他们允许("授权")做某些事情......例如. .."访问这个网站."

这种"身份验证+授权"服务可以由几种不同的技术提供,例如LDAP (Microsoft OpenDirectory)或Kerberos.

从您的观点来看,您只需知道:任何合法地在您的网站上结束的人必须伴随着[环境变量神奇地包含......]"令牌".(没有这样的代币必须是直接的理由404 Not Found.)

令牌的价值对你没有意义,但是,如果需要,"存在适当的手段",你的网站可以"[权威地]询问知道(LDAP ......等)的人"任何一个(!)你可能有的问题.换句话说,你没有利用任何 "本土逻辑".相反,你询问管理局并暗中信任其判决.

嗯......这是相当从精神开关"野生和毛茸茸的互联网."

  • 作为一个孩子,你在标点符号上跌倒了吗?:)我已经读了三遍,我仍然迷失在你想要做的那一点上.但如果您说"有时您不需要基于表单的身份验证",那么您是对的.但考虑到我们正在讨论何时需要它,我不明白为什么这一点非常重要? (8认同)
  • 即使是内部网也需要建筑物中的最低安全性.销售有保密的损益数字,而工程部门则拥有保密的知识产权.许多公司限制跨部门或部门的数据. (2认同)

jwilleke.. 5

使用OpenID Connect用户管理的访问.

因为没有比没有做更有效的事情.


提问时间:

查看次数:

565833 次

最近活跃:

3 月,4 周 前