我目前有一个PHP登录系统,它通过验证用户输入的组织代码来登录,因此查询的数据库会有所不同。
includes.php
<?php
mysql_connect("mysql.example.com", $dbconn, "MySecurePassword");
mysql_select_db($dbconn);
?>
login.php
// $org is the Organisation Code, will be set when user clicks Login
$dbconn = $org;
include "includes.php";
// Omitted the $userid & $pw variables, assume there is no error, and that MySQL Injection is prevented already
$query = "SELECT * FROM `Login` WHERE `userid`=TRIM('$userid') AND `password`=TRIM('$pw' )";
$result = mysql_query($query);
if(mysql_num_rows($result)>0){
session_start();
$_SESSION['logged_in'] = $username;
header("Location: loggedinpage.php");
}
loggedinpage.php
<?php
session_start();
// As there is no fixed database, I've omitted the DB Connection
define('DS', TRUE); // used to protect includes
define('USERNAME', $_SESSION['logged_in']);
define('SELF', $_SERVER['PHP_SELF'] );
// Checks if user is logged in
if (!USERNAME) {
header("Location: login.php");
}
?>
采取的安全措施
密码使用 SHA-512 进行哈希处理,不以明文形式存储。
使用
mysql_real_escape_string()
阻止 MySQL 注入
为了便于阅读,我省略了一些代码,我可以知道这种检查用户是否登录的方式是否安全吗?如果没有,我该如何改进它?
提前感谢!
- 更新
- 了问题以反映评论中的更新
假设您的查询按预期工作,并且仅在匹配完全正确时才返回一行(例如,通过排序规则没有奇怪的模糊匹配,而是纯粹的bin
比较(,身份验证部分几乎没问题。
(你已经被警告过很多SQL注入,你在那里靠自己。
然后,您的安全性归结为:
$_SESSION['logged_in'] = $username;
以及随后的:
define('USERNAME', $_SESSION['logged_in']);
if (!USERNAME) {
header("Location: login.php");
}
我想你的问题是关于这部分的。
那么答案是:会话部分没问题,阻塞部分不行。
这就是会话的使用方式,是的,默认情况下它们是相当安全的;用户将无法以某种方式自己设置$_SESSION['logged_in']
值,该值只能由您的服务器设置,并且可能您只有在成功进行身份验证时才这样做。请阅读有关会话劫持的信息,这是整个计划唯一真正的漏洞。
真正的问题是:
if (!USERNAME) {
header("Location: login.php");
}
设置页眉不会终止当前页面。如果您在此行之后输出敏感信息,它将被发送给客户端!您需要在设置标头后显式exit
。
说了这么多,我们无法告诉您您的系统是否"安全",因为您可能创建了我们没有看到的任意数量的 facepalm 后门。一般来说,我会从以下内容开始:
- 停止使用
mysql
,使用PDO
或mysqli
- 绑定你的参数,不要
mysql_real_escape_string
它们;那里有安全陷阱 - 使用
password_hash
密码哈希,而不是 SHA;特别是如果您只执行一次 SHA 传递
小心
值
SQL注入:
如果您在密码字段中输入:
''=''
密码的规则将为真,因为密码 = TRIM(''='( 为真。您必须控制密码的字符串:
- 最小长度
- 没有空格(得益于修剪功能(
而且您不必像这样存储密码,您必须创建密码的哈希