1

第一次为网页创建登录系统,我一直在尝试阅读有关安全性的信息,但不确定我是否做得对。

到目前为止,我已经存储了一个用户名/密码,并且密码是用 sha256 和一个 3 char salt 散列的。如果用户名和密码正确,那么我会像这样创建一个新的会话 ID

session_regenerate_id (); 
$_SESSION['valid'] = 1;
$_SESSION['userid'] = $userid;

在我检查的每一页

function isLoggedIn()
{
if(isset($_SESSION['valid']) && $_SESSION['valid'])
    return true;
return false;
}

我用它来检查正确的用户

$username = $_POST['username'];
$password = $_POST['password'];
//connect to the database here
connect();
//save username
$username = mysql_real_escape_string($username);
//query the database for the username provided
$query = "SELECT password, salt
    FROM users
    WHERE username = '$username';";
$result = mysql_query($query);
if(mysql_num_rows($result) < 1) //no such user exists
{
  //show incorrect login message
}
//check the password is correct for the username found
$userData = mysql_fetch_array($result, MYSQL_ASSOC);
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
if($hash != $userData['password']) //incorrect password
{
  //show incorrect login message
}
else
{
//setup a new session 
validateUser();
//redirect to the main page
header('Location: main.php');
die();

如果它是假的,那么他们会被发送回登录页面。这足够安全吗?

在主页中,我也有 html 链接

  <li><a href="main.php">Home page</a>

所以我需要在使用这些链接时在主页上结束 php 脚本?

4

5 回答 5

4

添加到phpdev所说的内容。尽管它看起来足够安全,但我还是推荐了几件事。

当您想将用户发送到某个页面时,请确保您的脚本退出并完成执行,因为如果仍有一些行,它们将被执行。以此为例:

if (!isLoggedIn()){
   header('Location: login.php');
}
//It's wrong to assume that things are safe here
echo $secret_data;

所以请确保您添加exit();die();在您的header()电话之后。

此外,在散列时,请确保为每个用户使用唯一的盐,因此您需要在表中创建一个额外的列users来存储salt散列密码的旁边。还强烈建议使用经过良好测试的散列库,例如PHPass

如果您在使用相同域的同一 Web 服务器上运行不同的 Web 服务,例如: mysite.com/my_super_awesome_appmysite.com/my_not_very_awesome_app确保您在$_SESSION类似的变量名称中添加前缀$_SESSION['app1_valid']或使用session_set_cookie_params()

于 2012-07-13T10:00:47.707 回答
3

是的,这对我来说看起来很安全。只要确保你session_start()在做任何事情之前打电话并小心你设置的位置$_SESSION['valid']。确保仅在您确认他们输入了正确的用户名和密码后才设置。

至于加盐,我建议为每个用户使用大约 10 个字符的独特盐。然后使用crypt和河豚算法 (bcrypt)对结果进行哈希处理。BCrypt 的设计使得计算散列的成本越来越高,如果有人窃取了你的密码散列,这一点很重要。

于 2012-07-13T09:45:05.327 回答
2

不要忘记从登录表单向前要求 HTTPS,否则这一切都是徒劳的。

于 2012-07-13T20:00:28.527 回答
0

对于一个基本的应用程序来说,它看起来不错。你可以做的事情还有很多。计时器。字典攻击。登录尝试会话。搜索 SO。

function is_customer_logged_in() {
    if($_COOKIE['GC_CUST_LOGIN']==1 && $_SESSION["loggedIn"]=="1"){
        return true;
    }else{
        return false;
    }
}

$_SESSION["time"]=time();
setcookie("GC_CUST_LOGIN", 1, ".stackoverflow.com");
$_SESSION["loggedIn"]="1";
$_SESSION["loggedIn_Md5_Hash"]=md5(hash);

您还可以为会话插入哈希值,检查是否已登录并添加一个数字,还可以在数据库检查后使用 cookie 和会话强制匹配。

于 2012-07-13T10:03:39.603 回答
0

密码安全性需要考虑很多事情。不幸的是,sha-256 仍然无法击败 bcrypt 或 scrypt(它们实现了密钥拉伸、盐和可扩展的工作因子以帮助硬件改进)。

我会通过 openwall (http://www.openwall.com/phpass/) 查看 PHPass,这是一个非常标准的 bcrypt 库,并且易于使用。

就像其他人所说的那样,除非您的登录页面通过 HTTPS 保护,否则仍然可以嗅探密码。

我喜欢你正在重新生成 session_id。虽然在这种情况下可能无关紧要,但它有助于防止会话重放或会话固定攻击。

总体而言,要使您的系统更安全,还需要考虑其他一些事项:

  • 密码政策
    • 密码长度
    • 数字+特殊字符
  • 密码短语
    • 如果你能确保单词不常见,可能会有更多的熵
  • 登录尝试失败后禁止
  • 添加双重身份验证
于 2012-07-14T04:54:58.270 回答