从使用 axios 调用响应启动 php 会话不会使会话保持活动状态,但使用邮递员执行它就可以了

Posted

技术标签:

【中文标题】从使用 axios 调用响应启动 php 会话不会使会话保持活动状态,但使用邮递员执行它就可以了【英文标题】:Starting a php session from react with an axios call does not keep the session alive, but doing it with postman works just fine 【发布时间】:2021-09-18 20:44:36 【问题描述】:

我知道存在类似这样的其他问题,但我未能成功实施其中任何一个,这意味着没有一个有效,无论是由于我自己的错误还是他们固有的无能解决这个问题。

环境:

我正在使用 php -S 127.0.0.1:8080 为 php 项目提供服务,并使用 npm start 在默认端口 (3000) 上启动了一个反应前端。我正在使用 axios 向服务器发出请求。

相关代码:

我有 2 个非常重要的文件:

Lo​​ginPage.js 是我的反应代码所在的位置,我发出 2 个请求,第一个是模拟身份验证并启动会话,第二个请求是检查会话是否仍然存在:
useEffect(() => 
    axios(
      method: "get",
      url: "http://localhost:8080/phpfolder/test1page.php?username=username",
      dataType: "JSON",
    )
      .then((response) => 
        console.log("response here", response.data);
        setUserName(response.data);
      )
      .catch((error) => 
        console.log(error);
      );
  , []);

  useEffect(() => 
    if (userName !== "") 
      axios(
        method: "get",
        url: "http://localhost:8080/phpfolder/test1page.php",
        dataType: "JSON",
      )
        .then((response) => 
          console.log("response here", response.data);
        )
        .catch((error) => 
          console.log(error);
        );
    
  , [userName]);
test1page.php 是我的 php 代码所在的位置:
    <?php 
     session_start();
     header("Access-Control-Allow-Origin: *");
     header('Access-Control-Allow-Headers: Content-Type');
    
     if (isset($_GET['username'])) 
        $_SESSION['username'] = $_GET['username'];
        // echo  $_SESSION['username'];
     
    
     if(!isset($_SESSION['username']))
        echo 'you are not logged in';
    else
        echo 'you are logged in';
        header('Content-type: application/json');
        echo json_encode($_SESSION);
    
    
     ?>

问题:

我的问题是,虽然第一个请求验证没有问题:

you are logged in"username":"username"

第二个请求没有找到实时会话:

you are not logged in

尝试过的解决方案/调试:

我尝试了很多解决方案,包括设置withCredentials: falsetrue。将其设置为 true 会导致 Cors 错误。我已经从 php 文件中添加和删除了各种头文件(一些用于 Cors,一些用于解决这个问题):

header("Access-Control-Allow-Headers: *");
header("Access-Control-Allow-Origin: http://localhost:3000");
header('Access-Control-Allow-Origin: *'); 
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Disposition, Content-Type, Content-Length, Accept-Encoding");
header("Content-type:application/json");
header("connection:keep-alive");

我已经尝试过邮递员并发送一个请求来启动会话,然后另一个来检查它是否还活着就可以了:

第一个请求:

第二次请求:

【问题讨论】:

我的第一个猜测是会话 cookie 没有在第一个请求中正确存储,或者它没有在第二个请求中发送。您可以尝试使用以下答案中的withCredentials 或类似名称吗:***.com/a/43178070/231316 您是否为 both 请求将 withCredentials 设置为 true?我不仅指定 cookie 是否与跨域请求一起发回,它还首先确定浏览器是否会接受 received cookie。 我做了,但是将 withCredentials 设置为 true 会导致 Cors 错误。 【参考方案1】:

我找到了解决方案。关于 Cors 的详细解释可以在 this article 中找到。相关部分在 Credentials and Cors 部分。 简短的回答是您必须将 withcredentials 标志设置为 true,这将导致 Cors 错误问题,然后您可以通过在后端添加适当的标头来解决此问题:

header("Access-Control-Allow-Origin: http://localhost:3000");
header("Access-Control-Allow-Credentials: true");

这就是我的页面现在一切正常的样子:

Lo​​ginPage.js :

    useEffect(() => 
        axios(
          method: "get",
          url: "http://localhost:8080/phpfolder/test1page.php?username=username",
          dataType: "JSON",
          withcredentials: true
        )
          .then((response) => 
            console.log("response here", response.data);
            setUserName(response.data);
          )
          .catch((error) => 
            console.log(error);
          );
      , []);
    
      useEffect(() => 
        if (userName !== "") 
          axios(
            method: "get",
            url: "http://localhost:8080/phpfolder/test1page.php",
            dataType: "JSON",
            withcredentials: true
          )
            .then((response) => 
              console.log("response here", response.data);
            )
            .catch((error) => 
              console.log(error);
            );
        
      , [userName]);

test1page.php:

 <?php 
  session_start();
  header("Access-Control-Allow-Origin: http://localhost:3000"); // cannot be a wildcard, you have to specify the name of the domain making the request here.
  header('Access-Control-Allow-Headers: Content-Type');
  header("Access-Control-Allow-Credentials: true"); // add this header

  if (isset($_GET['username'])) 
     $_SESSION['username'] = $_GET['username'];
     // echo  $_SESSION['username'];
  

  if(!isset($_SESSION['username']))
     echo 'you are not logged in';
  else 
     echo 'you are logged in';
     header('Content-type: application/json');
     echo json_encode($_SESSION);
 

  ?>

【讨论】:

以上是关于从使用 axios 调用响应启动 php 会话不会使会话保持活动状态,但使用邮递员执行它就可以了的主要内容,如果未能解决你的问题,请参考以下文章

axios 不会分别返回响应和错误

从 iOS 应用程序调用脚本时未维护 PHP 会话数组

如何从我得到的数组中获取特定的数组元素作为调用 axios.get() 调用的函数的响应 [重复]

使用 Axios/React Native 处理 PHP 响应

成功调用 axios 后,Vue.js 组件不会发送到父级

在 Heroku 部署中响应对 Express API 的 axios 调用