2

我编写了一个简单的 PHP 应用程序 (MyApp),它允许用户使用 Evernote 的 PHP SDK 登录到他们的 Evernote 帐户。但是,在我的应用程序中,我想这样做:

  1. 用户批准 Evernote 登录
  2. MyApp 接收#1 的 requestToken、requestTokenSecret 等。
  3. MyApp 将 #2 存储到 cookie 中,然后$_SESSION
  4. 当用户稍后返回我的网站时,MyApp 通过 cookie 将他们登录

是的,我知道这种基于 cookie 的登录是不安全的。然而,我的应用程序不存储敏感数据。最简单的方法是什么?这是我的尝试:

//if cookie
if (isset($_COOKIE['requestToken'])) {
    $m = new mysqli(MYSQL_SERVER, MYSQL_USER, MYSQL_PASS, MYSQL_DB);
    $q = "SELECT uid FROM users WHERE token={$_COOKIE['requestToken']} and secret={$_COOKIE['requestTokenSecret']}";

   // cookie matches db?
   if ($result = $m->query($q)) { 
      $_SESSION['login']=TRUE;
      $result->close();
}
   else // no match
      $_SESSION['login']=FALSE; 
}
else { //no cookie - create
    if (EverNoteLogin()) {
       $year=time()+86400*365; //86400 = 1 day
       setcookie('requestToken',$_SESSION['requestToken'],$year); 
       setcookie('requestTokenSecret',$_SESSION['requestTokenSecret'],$year);
    }
}

建议改进版本

//if cookie
if (isset($_COOKIE['requestToken'])) {
    //check db
    $m = new mysqli(MYSQL_SERVER, MYSQL_USER, MYSQL_PASS, MYSQL_DB);
    $s=$m->prepare("SELECT uid FROM user WHERE token=? AND secret=?");
    $s->bind_param('ss',$rt, $rs);
    $rt=$_COOKIE['requestToken'];
    $rs=$_COOKIE['requestTokenSecret'];
    $s->execute();
    $s->store_result(); 
    $n=$s->num_rows;
    //match db?
    if ($n) {
        if ($n==1) { // 1 match
                $s->bind_result($uid);
                $_SESSION['uid']=$uid;
                $_SESSION['login']=TRUE;
            }
        else
            $_SESSION['login']=FALSE; // >1 match not good
    }else
        $_SESSION['login']=FALSE;
}
else { //no cookie - create
    if (EverNoteLogin()) {
       $year=time()+86400*365; //86400 = 1 day
       setcookie('requestToken',$_SESSION['requestToken'],$year); 
       setcookie('requestTokenSecret',$_SESSION['requestTokenSecret'],$year);
    }
}
4

2 回答 2

0

我认为从 SQL 注入的角度来看,使用准备好的语句的脚本版本看起来很合适。

我当然也建议您将 cookie 设置为安全 cookie(因此需要 https 连接)和仅 http cookie(从而防止访问 javascript 等)。

于 2012-11-02T16:05:27.710 回答
0

在您展示的情况下,使用bind_param是对 SQL 注入的有效防御。现在,cookie 中的值是什么并不重要,它们不能改变 SQL 语句的语义。

SQL 查询中的参数占位符始终用作单个标量值。如果该值恰好包含 SQL 语法,那没关系,它会像您将带引号的字符串放入查询中一样,并且每个特殊字符都完美转义。为了避免 SQL 注入漏洞,完全安全。

您可以在我的演示文稿SQL 注入神话和谬误中或在我的书SQL 反模式:避免数据库编程的陷阱中阅读有关 SQL 注入的更多信息。

然而,不安全的是将身份验证凭据以明文形式存储在 cookie 中。 不要那样做。
另请参阅将密码存储在 cookie 中是否安全?如何在 PHP 中安全地存储包含敏感数据的 cookie?

于 2012-11-02T16:29:01.690 回答