【问题标题】:Token Do Not Work On Fetch Request To PHP File令牌对 PHP 文件的获取请求不起作用
【发布时间】:2021-04-29 04:56:26
【问题描述】:

我有两个文件:一个是公开会话令牌,另一个是回答 javascript-fetch。 文件一包含:

<?php
session_start();
unset($_SESSION['sessionToken']);
$_SESSION['sessionToken'] = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));
?><!DOCTYPE HTML>
<html>
...
    <meta content="<?php echo $_SESSION['sessionToken'] ?? '12345'; ?>" name="csrf-token" />

然后我在同一个文件中提出这样的获取请求:

fetch('src/exposeDelivery.php', {      
           //mode: 'same-origin',
           credentials: 'same-origin',     //'same-origin'    'omit'     'include
           method: 'POST',
           body: JSON.stringify( jsonArr ),
           headers: {
            'x-csrf-token':  document.head.querySelector('meta[name="csrf-token"]').content,
            "Content-Type": "application/json",
            "Accept":       "application/json"
           }
      })
        .then(response => {
          if (!response.ok) {
            console.log("response: %s  | %o",response.statusText,response);
            throw new Error('Network response was not ok');
          }
          return response.json();
        })

获取请求以类似 let ask = setInterval(makeRequest, 20000); 的间隔运行

我的第二个文件,即请求所在的位置,如下所示:

    <?php
    session_start();
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST');
    header('Access-Control-Allow-Headers: Content-Type, X-Requested-With, x-csrf-token');
    $csrf = isset($_SERVER["HTTP_X_CSRF_TOKEN"])
          ? trim($_SERVER["HTTP_X_CSRF_TOKEN"])
          : 0;
    $response['t_token']= $csrf;
    $response['sessionToken'] = $_SESSION['sessionToken'] ? $_SESSION['sessionToken'] : "noSessionToken";

    header('HTTP/1.0 200 OK');
    header('Content-Type: application/json');

    echo json_encode($response);

现在我想检查$csrf == $_SESSION['sessionToken']
这是我第一次将 fetch-request 称为 true。但是第二次调用请求时,它是不同的。这里有什么问题? File one 的 fetch-request 在每个请求上都会调用自己吗?我可以通过另一个请求来解决它吗?

【问题讨论】:

  • 如果您不确定实际发生了什么请求,请使用浏览器开发工具的网络面板进行查找。
  • 我就是这么做的。在第一个响应中 $response['t_token'] == $response['sessionToken']。在第二次通话中不再相等。
  • 你有session_destroy吗?您也可以尝试使用 fetch 不发出缓存请求,就像在这篇文章中解释的那样:stackoverflow.com/questions/29246444/…
  • of curse 不是第二个文件中 $_SESSION['sessionToken'] 的任何定义。这就是为什么我假设每个请求都会调用第一个文件。但我不知道。
  • 您是否考虑过记录这两个值以查看两个更改中的哪一个?

标签: javascript php ajax fetch


【解决方案1】:

看来您正在取消设置 $_SESSION['sessionToken'] 变量,因此它每次都会生成新值。删除第一个文件中的第 3 行,您就可以开始了。

【讨论】:

    【解决方案2】:

    我无法重现您提到的错误。
    我认为原因是 php 代码是在服务器端执行的,因此它在 before javascript 代码之前执行,该代码通过 POST 调用服务器。此时,您的服务器 api 调用与 javascript 代码具有相同的令牌。

    但是,我不明白您为什么每次都生成令牌。您可以改用此代码:

    if (!isset($_SESSION['sessionToken'])) {
        $token = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));
        $_SESSION['sessionToken'] = $token;
    }
    

    另一个原因可能是您为了验证令牌而进行的比较。
    不要使用===比较,而是使用hash_equals

    if (hash_equals($csrf, $_SESSION['sessionToken'])) {
         :
         :
    }
    

    【讨论】:

    • @hamburger,请接受答案或评论缺少的内容。人们为此付出了努力。
    • 对不起,我在医院,所以没能及时回复。这两个答案都没有帮助。我有一台租用的服务器。过了一会儿,代码现在仍然按预期工作。所以所有人都说他们无法重现错误是正确的。我认为服务器变量存在一些问题。感谢所有帮助者。
    猜你喜欢
    • 2020-09-18
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    • 2016-05-23
    • 2021-03-01
    • 1970-01-01
    相关资源
    最近更新 更多