为了账号安全,请及时绑定邮箱和手机立即绑定

如何在React中使用窗口的beforeunload事件执行axios代码

如何在React中使用窗口的beforeunload事件执行axios代码

PHP
凤凰求蛊 2023-11-03 16:47:31
我正在使用 React 和 PHP,我需要它来做一些特定的事情。我正在使用 Axios 向我的 PHP 页面发送请求,然后更改我的数据库。我需要更新我的 MySQL 数据库表,如果用户关闭页面或浏览器,则将is_logged值从true更改为false 。执行此操作的代码在窗口的beforeunload事件中设置。但是,数据库永远不会更新。我想要做的事情在 React 中是可能的吗?这是我的 React 组件代码:import React, { useState, useEffect } from 'react';import axios from 'axios';import Viewers from './Viewers';const Live = ({ match }) => {  window.addEventListener("beforeunload", () => {    axios.get('http://localhost/live-streaming-app/get_viewers.php?=' + token)      .then(response => console.log(response))  })  // Set token from url  const token = match.params.token  //Get the fullname and update logged_in to true  const [fullname, setFullname] = useState("")  useEffect(() => {    axios.get('http://localhost/live-streaming-app/get_user.php?token=' + token)      .then(response => {        setFullname(response.data.fullname)        console.log("Data", response.data)      })      .catch(error => console.log(error))    return () => {      axios.get('http://localhost/live-streaming-app/get_viewers.php?=' + token)        .then(response => console.log(response))        .catch(error => console.log(error))    }  }, [token])  //Jsx for when user is unauthorised  const rejected = (    <div className="container text-center pt-5">      <h1>Rejected Connection</h1>      <p>You are unauthorised to view this page</p>    </div>  )  let my_render = ""  if (fullname && fullname != null) {    my_render = <Viewers fullname={fullname} />  } else {    my_render = rejected  }  return my_render};export default Live;这是名为的 PHP 页面:<?phprequire 'connect.php';$token = $_GET['token'];$sql = "UPDATE `viewers` SET `logged_in`='false' WHERE `live_token`='{$token}'";if(mysqli_query($con, $sql)){  http_response_code(201);}else {  http_response_code(422);}exit;
查看完整描述

2 回答

?
芜湖不芜

TA贡献1796条经验 获得超7个赞

需要处理的问题:


请求是否已发送?

尝试跑步


axios.get('http://localhost/live-streaming-app/get_viewers.php?=')

  .then(response => console.log(response))

在浏览器控制台中查看控制台中是否记录了任何内容。还要检查开发工具中的“网络”选项卡,以查看是否发送了请求。如果请求已发送,则请求的发送有效。如果没有,则说明 URL 存在一些问题,需要修复。


代币

发送此请求


axios.get('http://localhost/live-streaming-app/get_viewers.php?=' + token)

  .then(response => console.log(response))

表示空字符串的值为token。另一方面,您的 PHP 代码假设有一个名为 的参数token:


<?php

require 'connect.php';


$token = $_GET['token']; //This is the line which assumes that a parameter called token exists


$sql = "UPDATE `viewers` SET `logged_in`='false' WHERE `live_token`='{$token}'";

if(mysqli_query($con, $sql)){

  http_response_code(201);

}

else {

  http_response_code(422);

}


exit;

为了符合 PHP 代码的假设,您需要指定token名为 的参数的值token:


  window.addEventListener("beforeunload", () => {

    axios.get('http://localhost/live-streaming-app/get_viewers.php?token=' + token)

      .then(response => console.log(response))

  })

上面的修复应该可以解决您所询问的问题,但我们不要就此停止。


SQL注入

如果我从浏览器控制台(或 cURL)发送此请求(不要运行它,除非您创建备份)会怎样:


axios.get("http://localhost/live-streaming-app/get_viewers.php?token=';delete from viewers where ''='")

  .then(response => console.log(response))

?


然后你的 PHP 代码将执行:


UPDATE `viewers` SET `logged_in`='false' WHERE `live_token`='';delete from viewers where ''=''

viewers从数据库中删除所有内容。使用PDO参数化您的查询并使您的查询免受此类攻击。


概括

React 是一个 Javascript 框架,这意味着无论 Javascript 能做什么,你的客户端也能做到。确实,某些功能不一定以 React 方式可用,但假设 Javascript 能够做到这一点,那么您不必担心这些功能是否可行。我倾向于认为,当客户端发生很多事情时,客户端框架将变得不太有用,并且我认为客户端框架流行的主要原因是大多数程序员没有意识到有多少Javascript 能够做到的事情。我并不是说永远不应该使用客户端框架。我只是说,我见过程序员盲目迷恋客户端框架和技术,最终毁掉了他们所从事的项目。因此,当您选择客户端技术堆栈时,值得检查客户端所需的功能、不使用客户端框架实现它所需的时间以及使用您可能考虑的每个框架实现它所需的时间使用。比较两者并考虑截止日期和财务能力。如果您找不到使用客户端框架的明显且很好的理由,那么我建议不要使用它。因为,归根结底,如果在开发过程中由于某种原因您需要使用客户端框架,您可以轻松地从不使用框架的位置转向它。但是,如果您正在使用客户端框架,并且事实证明它对您的项目不可行,那么重构整个项目以不使用该框架通常意味着重新实现大部分客户端。而这种问题往往不会在紧急情况下显现出来。


查看完整回答
反对 回复 2023-11-03
?
慕森卡

TA贡献1806条经验 获得超8个赞

无法保证事件中执行的异步操作beforeunload将会完成,axios 使用异步方式发出请求。


您或许可以使用老式的 XHR 来发出同步请求。如果您转到标记为 的部分Adapting Sync XHR use cases to the Beacon API,他们将讨论在卸载期间保持请求活动的策略,因为同步 XHR 已被弃用。


请注意,同步 HTTP 请求通常不是一个好主意,因为它们会在完成时导致页面无响应。我不确定卸载期间同步请求的行为是什么。


同步请求示例


logUser () {

    var params = JSON.stringify({ locked_by: '' });

    let xhr = new XMLHttpRequest()

    xhr.open('PUT',Url, false) // `false` makes the request synchronous

    xhr.setRequestHeader("Authorization", 'Bearer ' + localStorage.getItem('app_access_token'))

    xhr.setRequestHeader("Content-length", params.length);

    xhr.setRequestHeader("Content-type", "application/json; charset=utf-8")

    xhr.responseType = 'arraybuffer'

    xhr.onreadystatechange = function() {//Call a function when the state changes.

    if(xhr.readyState == 4 && xhr.status == 200) {

        alert(xhr.responseText);

    }

}


笔记


没有可靠的方法可以在选项卡/窗口关闭时执行某些操作。这违背了“关闭”选项卡(即释放资源)的原则。


我处理你的情况的方法是让前端保存一些在选项卡关闭时自行消失的东西。


要么打开一个可用于许多其他目的的 websocket,当它死机并且在几秒钟内没有返回时,您就知道客户端已断开连接,或者在选项卡打开时以及错过了某个时间时发送常规 ping几次 ping 操作后,您就可以安全地假设客户端已断开连接。


查看完整回答
反对 回复 2023-11-03
  • 2 回答
  • 0 关注
  • 109 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信