在服务器端验证 curl CURLOPT_HTTPHEADER 请求
Validate curl CURLOPT_HTTPHEADER request on server side
我开发了一个小型网络服务,它将用户查询和 returns 数据作为 json 响应。一切正常。但我想知道如何设置和比较
来自客户端的授权令牌作为 curl header 的一部分。这是我发送请求的代码。我仍然没有在 FetchData.php 上设置任何验证。我想在 FetchData.php 上实现它。如何实施?
$query = "select * from product_details where id = 2";
$query_params = array("query" => $query);
$url = "http://localhost/api/fetchData.php?" . http_build_query($query_params, '', "&");
$curl = curl_init();
$token = 'ABCD123456';
$header[] = 'Authorization: Token '.$token;
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $url,
CURLOPT_HTTPGET=>1,
CURLOPT_FAILONERROR=> 1,
CURLOPT_RETURNTRANSFER=> true,
CURLOPT_HTTPHEADER=>$header
));
$resp = curl_exec($curl);
if($resp === false)
{
$responseJson = new stdClass();
$responseJson->status = "FAILED";
$responseJson->message = 'Send error: ' . curl_error($curl);
throw new Exception(curl_error($curl));
}
else{
$resp = curl_exec($curl);
}
在上面的代码中我添加了这个授权令牌。但实际上这不是在服务器端设置的,我的意思是 fetchData.php
.
$token = 'ABCD123456';
$header[] = 'Authorization: Token '.$token;
所以我的问题是如何在 fetchData.php
中设置此授权令牌并验证来自客户端的令牌?任何帮助将不胜感激。
如果只有1个token,可以硬编码,
if(hash_equals(hash('sha384',$_SERVER['HTTP_AUTHORIZATION'],true),hash('sha384','the-real-token',true)){
// correct token!
}else{
// wrong token
}
但是,如果您有多个令牌,则应将它们预先散列保存在数据库中,这是一个包含令牌 "foo"、"bar" 和 "baz" 的 SQLite 示例:
$db = new PDO('sqlite::memory:', '', '', array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
$db->exec('
CREATE TABLE tokens(id INTEGER PRIMARY KEY AUTOINCREMENT,
token TEXT,
hash BLOB);');
$stm=$db->prepare("INSERT INTO TOKENS(`token`,`hash`) VALUES(:token,:hash);");
$tokens=["foo","bar","baz"];
foreach($tokens as $token){
$stm->execute(array(':token'=>$token,':hash'=>hash('sha384',$token,true)));
}
有了这个,您可以通过 运行
检查令牌是否有效
$stm=$db->prepare("SELECT EXISTS(SELECT 1 FROM hashes WHERE hash=?);");
$stm->execute([hash('sha384',$_SERVER['HTTP_AUTHORIZATION'],true]);
if($stm->fetch(PDO::FETCH_NUM)[0]==="1"){
// valid token!
}else{
// invalid token =(
}
现在你可能会想
why bother hashing the tokens at all, why not just save them in plaintext?
它是关于防止定时攻击的,哈希会进行长度填充,因此黑客无法使用定时攻击来推断令牌的实际长度(这可以帮助攻击者执行很多操作) bruteforce/dictionary 攻击),实际令牌、输入字符串和定时攻击的正确位数之间没有关联,即使黑客设法推断出 the first 8 bits of the hash is definitely 10010111
,它越来越难找到一个字符串,该字符串对于被推断的每个位散列为 known-bits+1,最终结果是用定时攻击攻击这个方案应该是完全不可行的(至少对于 sha2-384)
我开发了一个小型网络服务,它将用户查询和 returns 数据作为 json 响应。一切正常。但我想知道如何设置和比较 来自客户端的授权令牌作为 curl header 的一部分。这是我发送请求的代码。我仍然没有在 FetchData.php 上设置任何验证。我想在 FetchData.php 上实现它。如何实施?
$query = "select * from product_details where id = 2";
$query_params = array("query" => $query);
$url = "http://localhost/api/fetchData.php?" . http_build_query($query_params, '', "&");
$curl = curl_init();
$token = 'ABCD123456';
$header[] = 'Authorization: Token '.$token;
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $url,
CURLOPT_HTTPGET=>1,
CURLOPT_FAILONERROR=> 1,
CURLOPT_RETURNTRANSFER=> true,
CURLOPT_HTTPHEADER=>$header
));
$resp = curl_exec($curl);
if($resp === false)
{
$responseJson = new stdClass();
$responseJson->status = "FAILED";
$responseJson->message = 'Send error: ' . curl_error($curl);
throw new Exception(curl_error($curl));
}
else{
$resp = curl_exec($curl);
}
在上面的代码中我添加了这个授权令牌。但实际上这不是在服务器端设置的,我的意思是 fetchData.php
.
$token = 'ABCD123456';
$header[] = 'Authorization: Token '.$token;
所以我的问题是如何在 fetchData.php
中设置此授权令牌并验证来自客户端的令牌?任何帮助将不胜感激。
如果只有1个token,可以硬编码,
if(hash_equals(hash('sha384',$_SERVER['HTTP_AUTHORIZATION'],true),hash('sha384','the-real-token',true)){
// correct token!
}else{
// wrong token
}
但是,如果您有多个令牌,则应将它们预先散列保存在数据库中,这是一个包含令牌 "foo"、"bar" 和 "baz" 的 SQLite 示例:
$db = new PDO('sqlite::memory:', '', '', array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
$db->exec('
CREATE TABLE tokens(id INTEGER PRIMARY KEY AUTOINCREMENT,
token TEXT,
hash BLOB);');
$stm=$db->prepare("INSERT INTO TOKENS(`token`,`hash`) VALUES(:token,:hash);");
$tokens=["foo","bar","baz"];
foreach($tokens as $token){
$stm->execute(array(':token'=>$token,':hash'=>hash('sha384',$token,true)));
}
有了这个,您可以通过 运行
检查令牌是否有效$stm=$db->prepare("SELECT EXISTS(SELECT 1 FROM hashes WHERE hash=?);");
$stm->execute([hash('sha384',$_SERVER['HTTP_AUTHORIZATION'],true]);
if($stm->fetch(PDO::FETCH_NUM)[0]==="1"){
// valid token!
}else{
// invalid token =(
}
现在你可能会想
why bother hashing the tokens at all, why not just save them in plaintext?它是关于防止定时攻击的,哈希会进行长度填充,因此黑客无法使用定时攻击来推断令牌的实际长度(这可以帮助攻击者执行很多操作) bruteforce/dictionary 攻击),实际令牌、输入字符串和定时攻击的正确位数之间没有关联,即使黑客设法推断出
the first 8 bits of the hash is definitely 10010111
,它越来越难找到一个字符串,该字符串对于被推断的每个位散列为 known-bits+1,最终结果是用定时攻击攻击这个方案应该是完全不可行的(至少对于 sha2-384)