我有一个网站,我让用户输入他们的用户名/传递给登录并将此信息存储在一个文件中。这是我目前的代码:
function getPassword( $user )
{
$passwords= array
(
'Admin' => '123456',
'Moderator' => 'abcde'
);
eval(file_get_contents('./login.info')); //<--- THIS is where usernames/passwords are stored
$password = $passwords[ $user ];
if ( NULL == $password )
return NULL;
return array( $user, $password );
}
这是我为用户创建新帐户的代码:
<?php
if((isset($_POST['username']))and(isset($_POST['password']))){
$file = "login.info";
$fh = fopen($file, 'a');
//prevent sql injection
function check_field($fh)
{
if(!preg_match("/[^a-zA-Z0-9\.\-\_\@\.\+\~]/",$fh))
return TRUE;
else
return FALSE;
}
if(!check_field($_POST[username]))
{
header("Location:illegalchars.html");
break;
}
if(!check_field($_POST[password]))
{
header("Location:illegalchars.html");
break;
}
fwrite($fh, '$passwords["'.$_POST['username'].'"]="'.$_POST['password'].'";');
fclose($fh);
header("Location:success.html");
break;
}
?>
我知道我的代码不漂亮..并且存在重大问题
其中之一是:如果有人使用用户名x创建帐户,任何人仍然可以使用新密码创建x以获得控制权。
我的简单解决方案是将eval(file_get_contents('./login.info'));
移到管理员帐户之上,并将新帐户添加到新用户/通行证列表的顶部。但是,我无法弄清楚为什么将eval放在数组顶部不起作用。另外,我如何将代码添加到列表顶部。
任何帮助是极大的赞赏。
==编辑==我知道这个代码有很多批评,但有人可以回答这个问题吗?我现在并不是想提高安全性/性能(这是一个概念验证游戏,最终,整个事情都必须重写)。我只想要一个功能性脚本,请回答这个问题? :
答案 0 :(得分:2)
坦率地说,这里有一些重大问题。
零。您不应该存储明文密码。永远。使用单向散列,例如sha1()(不是md5)和盐,互联网上的大量手册。
一。使用eval()在性能和安全性方面都是不好的做法。寻求其他机制,他们总是在那里。
两个。你应该使用可靠的数据存储机制,而不是php文件。建议使用诸如mysql之类的RDBMS,它可以确保不会为用户创建重复记录。
三。您不应在用户名上添加任何特殊含义,例如admin或mod,将权限设为特殊字段,或者更好,请考虑使用基于角色的授权。
四个。如果没有适当的架构,您无法控制为某些用户运行的代码的安全性。考虑使用基于对象的MVC方法,您可以再次找到许多关于此的手册。
对不起,这听起来很重要,但我认为这比向您提供的代码发布补丁更好。
答案 1 :(得分:1)
如果你真的不能使用像openid这样的东西,那么你可以在这里查看my improved script到你的登录脚本(应该是最后的手段......)。
请为好爱而不要写自己的登录系统(不存储密码)。阅读Stackoverflow作者关于如何Lifehacker got hacked的这篇文章。我特别喜欢这句话,我完全赞同:
我不是来批评Gawker。上 相反,我要感谢他们 用粗略,大胆的浮雕来说明 关于网站的肮脏事实 密码:我们都会变得更好 没有他们。如果你想看到一个 未来的网络没有Gawker风格 密码妥协 - 停止信任 每个随机的网站都有一个 唯一的用户名和密码!需求 他们允许你使用你的 互联网驾驶执照 - 即 你现有的Twitter,Facebook, Google或OpenID凭据 登录他们的网站。
您应该使用例如openid(lightopenid)。阅读链接,了解将openid集成到您的网站是多么容易。
答案 2 :(得分:1)
OMG!
我可以在dailywtf上发布此内容。
eval和纯文本数据库没有内在错误,但前提是没有更好的方法来解决问题。即便如此,你应该广泛地过滤输入到eval并在数据库之上使用抽象。
每次要执行任何操作时,OTOH读取整个数据库都是完全错误的。
存储未加密的密码是错误的。
你说你不能使用mysql - 但是dbm怎么样? SQLite的?一个快速谷歌建议在纯文本或CSV文件之上运行许多平面文件抽象层。