PHP中使用$\u POST和$\u GET变量的最佳实践

PHP中使用$\u POST和$\u GET变量的最佳实践,php,postgresql,optimization,Php,Postgresql,Optimization,考虑到一个项目将有多个开发人员工作,并且将得到不断的更新和维护,考虑到可读性和安全性,以下两个代码中的哪一个可以被认为是PHP中的最佳实践?如果我们谈论绩效,但有办法解决这一点 选项1 $user = $_POST['user']; $pass = $_POST['pass']; // Prevent SQL Injection and XSS $user = anti_injection($user); $pass = anti_injection($pass); if(strlen($u

考虑到一个项目将有多个开发人员工作,并且将得到不断的更新和维护,考虑到可读性和安全性,以下两个代码中的哪一个可以被认为是PHP中的最佳实践?如果我们谈论绩效,但有办法解决这一点

选项1

$user = $_POST['user'];
$pass = $_POST['pass'];

// Prevent SQL Injection and XSS
$user = anti_injection($user);
$pass = anti_injection($pass);

if(strlen($user) <= 8 && strlen($pass) <= 12)
{
    // SQL query
    $sql = "SELECT id 
            FROM users 
            WHERE username = '$user' AND password = '$pass';";
}
$user=$\u POST['user'];
$pass=$_POST['pass'];
//防止SQL注入和XSS
$user=反_注入($user);
$pass=抗血栓注射($pass);

如果(strlen($user)这两个选项都不是最佳实践,如果只是针对可疑的
反U注入
,几乎肯定不会像广告中那样起作用。还有以下问题:

  • 在验证输入数据之前检查它们
  • 存储明文密码
  • 手动构造SQL查询,而不是使用绑定参数
根据项目的范围,最后一个可能是可接受的


关于性能,第一个选项在理论上会更快,因为它的数组索引更少。但是差异肯定会很小,以至于根本看不到。第一个选项也更可读,提供更好的抽象,所有这些都只需要很少的额外内存。

这两个选项都是错误的r将密码存储为纯文本,这只是自找麻烦


另外,如果我的用户名是
“123456”
,我将无法登录,因为您会将其转义到
“123456\”
,这将使“长度”失败,如果您想要安全性和性能,我建议使用PDO。在使用参数时不能进行sql注入。下面是一个示例,您需要“定义”“mysql参数使下面的工作正常

这还允许数据库缓存查询,因为它不会在每次使用不同的参数执行时更改,这也会提高性能

:p_user and :p_pass
用于表示参数和

array ( ':p_user' => $user, ':p_pass' => $pass ' )
将参数设置为需要传入的值

你还应该考虑添加一个密码盐,并把它的Sa1存储在数据库中,这样如果你的数据库被破坏了,你的密码就不会很清楚地显示给黑客。

class users{ 
  function __construct() {
    define('MySQLHost', 'localhost');
    define('MySQLName', 'databasename');
    define('MySQLUser', 'username');
    define('MySQLPass', 'password');
    define('pwsalt', 'tScgpBOoRL7A48TzpBGUgpKINc69B4Ylpvc5Xc6k'); //random characters
  }

  static function GetQuery($query, $params)
  {
    $db = new PDO('pgsql:host='.MySQLHost.';dbname='.MySQLName.';', MySQLUser, MySQLPass);
    $cmd = $db->prepare($query);
    $cmd->execute($params);

    if($cmd->rowCount()==0)
      return null;
    return $cmd->fetchAll();
  }

  static function GetUser($user, $pass)
  {
    $query = "select id
      from `users`
      where username = :p_user and password = :p_pass";

    $rows = users::GetQuery($query, array(
      ':p_user' => $user,
      ':p_pass' => sha1($pass.pwsalt) //Append the salt to the password, hash it
    ));

    return $rows;
  }
}

$user = $_POST['user'];
$pass = $_POST['pass'];
if( strlen($user) <= 8 && strlen($pass) <= 12 )
{
  $result = users::GetUser($user, $pass);
  if($result != null)
    print 'Login Found';
}
类用户{
函数_u构造(){
定义('MySQLHost','localhost');
定义('MySQLName','databasename');
定义('MySQLUser','username');
定义('MySQLPass','password');
定义('pwsalt','tScgpBOoRL7A48TzpBGUgpKINc69B4Ylpvc5Xc6k');//随机字符
}
静态函数GetQuery($query,$params)
{
$db=new-PDO('pgsql:host='.MySQLHost.';dbname='.MySQLName.';',MySQLUser,MySQLPass);
$cmd=$db->prepare($query);
$cmd->execute($params);
如果($cmd->rowCount()==0)
返回null;
返回$cmd->fetchAll();
}
静态函数GetUser($user,$pass)
{
$query=“选择id
来自`用户`
其中用户名=:p_user和密码=:p_pass”;
$rows=users::GetQuery($query,数组)(
':p_user'=>$user,
“:p_pass'=>sha1($pass.pwsalt)//将salt附加到密码后,对其进行散列
));
返回$rows;
}
}
$user=$_POST['user'];
$pass=$_POST['pass'];
如果(strlen($user)不这样做。
我只能假设
anti_injection
是某种定制过滤功能,这是个坏主意™. 如果你真的想采纳这两种想法,你应该使用
mysql\u real\u escape\u string

编写SQL查询时保持安全的唯一方法是使用参数,例如通过MySQLi。无论如何,
mysql.*
函数都不推荐使用,因此最好尽快使用

实际上,<代码> MySQL LealReleSeEXY字符串< /C> >不是对注入攻击的万无一失的防御。请考虑查询中的整数比较,如<代码> $var>30 < /代码>。我可以成功地将<代码> 1=1或100 < /代码>成功地输入<代码> $var < /代码>,并完全打破逻辑。

参数将数据与查询语言完全分离,完全降低了注入风险。服务器接收到一个包含参数符号的查询,以及一组要插入的值,因此它可以完全不同地处理查询语言和数据

此外,您似乎正在以明文形式存储密码。您应该研究一种强大的密码存储哈希算法,例如bcrypt,这使得从哈希中获取明文密码非常困难

MD5和SHA1对于密码存储来说并不理想,因为它们设计得很快,这意味着攻击者甚至可以快速破解强加盐密码。现代GPU每秒可以达到50亿MD5哈希。事实上,有些人有专门的哈希破解装备,其中一些可以在一个时间破解MD5

您还应该看看这些可怕的问题,它们完全涵盖SQL注入攻击、密码存储和许多其他安全问题:


更新:您提到您正在使用postgres。您可以使用从PHP运行参数化查询,如。

虽然我同意其他海报,但不要试图“重新发明”SQL安全性,问题似乎是性能和如何使用超全局

作为最佳实践,不要改变超全局变量($\u-GET、$\u-POST、$\u-REQUEST、$\u-SYSTEM等)。我想不出任何一个违反此规则会提高性能的例子,任何修改都会导致不确定性和混乱

因此,在这种情况下,两个选项都不正确。选项1不必要地复制了一个变量(根据Google performance docs的说法是否定的)。选项2变异了超全局变量,这违反了上述准则。相反,请执行以下操作:

$user = anti_injection( $_POST['user'] );
$pass = anti_injection( $_POST['pass'] );

if( strlen($user) <= 8 && strlen($pass) <= 12 ) ...
$user=anti_injection($_POST['user']);
$pass=抗-u注射($u-POST['pass']);

如果(strlen($user)如果你对安全感兴趣,wh
$user = anti_injection( $_POST['user'] );
$pass = anti_injection( $_POST['pass'] );

if( strlen($user) <= 8 && strlen($pass) <= 12 ) ...