php - 如何衡量密码的强度?

标签 php javascript password-protection

我一直在寻找一种有效的算法,可以让我准确了解密码的强度。

我发现几个不同的网站使用几种不同的算法,因为我在不同的网站上获得不同的密码强度评级。

最佳答案

这已经成为我在 PHP/MySQL 中使用密码的最佳实践的一般头脑转储。 这里提出的想法通常不是我自己的,而是我迄今为止发现的最好的想法。


确保您对涉及用户信息的所有操作都使用 SSL。涉及这些表单的所有页面都应检查它们是通过 HTTPS 调用的,否则拒绝工作。

您可以通过简单地限制允许的失败登录次数来消除大多数攻击。

允许使用相对较弱的密码,但会存储每个用户登录失败的次数,如果超过该次数,则需要通过电子邮件进行验证码或密码验证。我将最大失败次数设置为 5。

向用户呈现登录失败需要仔细考虑,以免向攻击者提供信息。 由于用户不存在而导致的登录失败应返回与由于密码错误而导致登录失败相同的消息。提供不同的消息将允许攻击者确定有效的用户登录。

另外,请确保在使用有效密码登录失败过多以及登录失败密码错误过多时返回完全相同的消息。提供不同的消息将允许攻击者确定有效的用户密码。相当多的用户在被迫重置密码时只会将其恢复原状。

不幸的是,限制每个 IP 地址允许的登录次数是不切实际的。 AOL 和大多数公司等多家提供商代理他们的 Web 请求。施加此限制将有效地消除这些用户。


我发现在提交之前检查字典单词效率低下,因为您必须在 javascript 中向客户端发送字典,或者为每个字段更改发送 ajax 请求。我这样做了一段时间,效果不错,但不喜欢它产生的流量。

使用一些简单的 javascript 检查固有的弱密码减去字典单词是实用的客户端。

提交后,我检查字典单词和包含密码的用户名,反之亦然服务器端。非常好的词典很容易下载,而且对它们进行测试也很简单。这里的一个问题是,要测试字典中的单词,您需要向数据库发送一个查询,该查询同样包含密码。我解决这个问题的方法是事先用简单的加密和结束定位的 SALT 加密我的字典,然后测试加密密码。不理想,但比纯文本更好,并且只在您的物理机器和子网上的人在线上使用。

一旦您对他们选择的密码感到满意,首先使用 PHP 对其进行加密,然后存储。下面的密码加密函数也不是我的主意,但是解决了一些问题。在 PHP 中加密可以防止共享服务器上的人拦截您未加密的密码。为每个用户添加一些不会改变的东西(我使用电子邮件,因为这是我网站的用户名)并添加一个散列(SALT 是一个简短的常量字符串,我在每个网站上更改)增加了对攻击的抵抗力。因为 SALT 位于密码中,而且密码可以是任意长度,所以几乎不可能用彩虹表来攻击它。 或者,这也意味着人们不能更改他们的电子邮件,并且您不能在不使每个人的密码无效的情况下更改 SALT。

编辑:我现在建议使用 PhPass而不是我在这里推出你自己的功能,或者完全忘记用户登录并使用 OpenID相反。

function password_crypt($email,$toHash) {
  $password = str_split($toHash,(strlen($toHash)/2)+1);
  return hash('sha256', $email.$password[0].SALT.$password[1]); 
}

我的 Jqueryish 客户端密码表。目标应该是一个 div。它的宽度将在 0 到 100 之间变化,背景颜色将根据脚本中指定的类而变化。同样大部分是从我发现的其他东西中偷来的:

$.updatePasswordMeter = function(password,username,target) {
$.updatePasswordMeter._checkRepetition = function(pLen,str) {
res = ""
for ( i=0; i<str.length ; i++ ) {
    repeated=true;
    for (j=0;j < pLen && (j+i+pLen) < str.length;j++)
        repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen));
    if (j<pLen) repeated=false;
    if (repeated) {
        i+=pLen-1;
        repeated=false;
    }
    else {
        res+=str.charAt(i);
    };
};
return res;
};
var score = 0;
var r_class = 'weak-password';
//password < 4
if (password.length < 4 || password.toLowerCase()==username.toLowerCase()) { 
target.width(score + '%').removeClass("weak-password okay-password good-password strong-password"
).addClass(r_class);
  return true;
} 
//password length
score += password.length * 4;
score += ( $.updatePasswordMeter._checkRepetition(1,password).length - password.length ) * 1;
score += ( $.updatePasswordMeter._checkRepetition(2,password).length - password.length ) * 1;
score += ( $.updatePasswordMeter._checkRepetition(3,password).length - password.length ) * 1;
score += ( $.updatePasswordMeter._checkRepetition(4,password).length - password.length ) * 1;
//password has 3 numbers
if (password.match(/(.*[0-9].*[0-9].*[0-9])/))  score += 5; 

//password has 2 symbols
if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5; 

//password has Upper and Lower chars
if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/))  score += 10; 

//password has number and chars
if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/))  score += 15; 
//
//password has number and symbol
if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/))  score += 15; 

//password has char and symbol
if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/))  score += 15; 

//password is just a nubers or chars
if (password.match(/^\w+$/) || password.match(/^\d+$/) )  score -= 10; 

//verifing 0 < score < 100
score = score * 2;
if ( score < 0 )  score = 0;
if ( score > 100 )  score = 100;
if (score > 25 ) r_class = 'okay-password';
if (score > 50  ) r_class = 'good-password';
if (score > 75 ) r_class = 'strong-password';
target.width(score + '%').removeClass("weak-password okay-password good-password strong-password"
).addClass(r_class);
return true;
};

关于php - 如何衡量密码的强度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1614811/

相关文章:

php - 检查是否在 PHP 中设置了变量

javascript - H1、H2 等的 Internet Explorer 命令标识符是什么?

javascript - 动态单选按钮未出现在 IE 中

ios - 客户端/服务器应用程序的散列用户密码

maven - mvn --encrypt-master-password <password> : Good practice for choosing <password>? 它应该是哪个级别的隐私?

javascript - 如何通过Javascript Post函数保护通过PHP运行的SQL

php - 使用 PHP unserialize() 多选标签中的多个选择值

Javascript:如何将带有字符串参数的函数作为参数传递给另一个函数

java - 在 spring boot 中定义重要凭据的最佳方式

php - 我想在我的数据库中搜索数组的键