php从cookie登录-一些SQL注入预防示例

php从cookie登录-一些SQL注入预防示例,php,mysql,sql-injection,evernote,Php,Mysql,Sql Injection,Evernote,我已经编写了一个简单的PHP应用程序(MyApp),允许用户使用Evernote的SDK for PHP登录到他们的Evernote帐户。但是,在我的应用程序中,我希望执行以下操作: 用户批准Evernote登录 MyApp接收#1的requestToken、requestTokenSecret等 MyApp将#2存储到一个cookie中,并$\u会话 当用户稍后返回我的站点时,MyApp会通过cookie将他们登录 是的,我知道这种基于cookie的登录是不安全的。但是,我的应用程序不存储敏感

我已经编写了一个简单的PHP应用程序(MyApp),允许用户使用Evernote的SDK for PHP登录到他们的Evernote帐户。但是,在我的应用程序中,我希望执行以下操作:

  • 用户批准Evernote登录
  • MyApp接收#1的requestToken、requestTokenSecret等
  • MyApp将#2存储到一个cookie中,并
    $\u会话
  • 当用户稍后返回我的站点时,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);
        }
    }
    

    我认为,从SQL注入的角度来看,使用prepared语句的脚本版本是合适的


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

    使用
    bind_param
    可以有效防止SQL注入。现在不管cookie中的值是什么,它们都不能更改SQL语句的语义

    SQL查询中的参数占位符始终充当单个标量值。如果该值恰好包含SQL语法,则无所谓,它的工作方式就像您将带引号的字符串放入查询中,每个特殊字符都进行了完美转义。完全安全,以避免SQL注入漏洞

    您可以在我的演示文稿或我的书中阅读有关SQL注入的更多信息

    然而,不安全的是,在cookie中以明文形式存储身份验证凭据不要那样做。

    另请参见或

    这易受SQL注入攻击<代码>$\u COOKIE是用户数据,不可信任。由于您使用的是MySQLi,因此这应该是一个准备好的语句,而不是一个
    query()
    调用。首先将$\u COOKIE信息存储在变量中,然后对其进行转义,即$token=mysql\u real\u escape\u string($\u COOKIE['requestToken');Juapo2,来自Mysql网站():“不鼓励使用此扩展。相反,应该使用MySQLi或PDO_Mysql扩展。”同意。除非我弄错了,否则oAuth requestToken(在cookie中)根据定义是“临时”的,没有oauthVerifier是无用的,它不会记录在任何cookie中。因此,cookie数据基本上已经是随机的了。那么,为什么要为临时令牌设置1年的过期期限呢?;-)