wwwwwllllk 发表于 2023-4-5 10:35:51

Fetch劫持方式补充

本帖最后由 wwwwwllllk 于 2023-4-5 10:37 编辑

看了道哥这篇文章的补充吧,避免在学的过程还需要百度其它知识点,感觉自己写的过程涉及到东西太多了,本来是看webpack劫持修改函数的,但是自己在实战的时候发现劫持请求可能更容易达到效果,我们在写脚本的时候其实正常来说不需要学这些东西就可以完成我们的需求,除非就要改变网站原来的逻辑或者请求参数返回结果就需要这样做了。

> 文章结合下面这篇文章看,我这里只作补充,把我学习的过程遇到的问题补充一下,也方便自己看方便


(https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=1020)


# 思路
1.当我们比如要对某一个网站按钮点击触发以后界面弹出一个alert弹框,这个时候正常来说点击一个按钮大多数情况是和后端会产生交互的,这个时候我们就可以通过xhr请求来定位到我们想看的位置。

# 实战
!(data/attachment/forum/202304/05/100129uz7x6ff7mwwl6f6c.png)

!(data/attachment/forum/202304/05/101133mga442zqxtrmamre.png)

!(data/attachment/forum/202304/05/101601abobgo9o8g7e92h8.png)

```javascript
let oldfetch = fetch;
function fuckfetch() {
    return new Promise((resolve, reject) => {
      oldfetch.apply(this, arguments).then(response => {
            const oldJson = response.json;
            response.json = function() {
                return new Promise((resolve, reject) => {
                  oldJson.apply(this, arguments).then(result => {
                        console.log(result)
                        alert('收藏成功')
                        resolve(result);
                  });
                });
            };
            resolve(response);
      });
    });
}
window.fetch = fuckfetch;
```

!(data/attachment/forum/202304/05/101758c6vzlivlwozrttx8.png)

### 这个只是简单的实战,从用途来说并没有任何意义,
### 我想做的是因为我发现语雀有个bug,反馈了还没解
### 决,所以正好尝试,我们实现的效果通过劫持实现当
### 我点击花园提示我收藏花园成功,点击前端提示我收
### 藏到前端成功

> 感觉有难度,我现在偷懒不搞了,希望有人搞成功分享一下

# 补充
看到这里可能会觉得道哥的代码似乎可以无脑用了,好像确实没毛病

但是当我们请求响应的内容是text的时候就需要稍微改一下了
```javascript
let oldfetch = fetch;
    function fuckfetch() {
      return new Promise((resolve, reject) => {
            oldfetch.apply(this, arguments).then(response => {
                const oldJson = response.text;

                response.text = function () {
                  return new Promise((resolve, reject) => {
                        oldJson.apply(this, arguments).then(result => {
                            console.log(result)
                            resolve(result);
                        });
                  });
                };

                resolve(response);
            });
      });
    }
```


顺便百度了一下call和apply的区别

```
当使用call时,因为它将参数作为单独的参数传递,如果您尝试传递多个参数,它将无法正常工作,例如:
oldfetch.call(this, url, options).then(response => {
// code
});

这段代码试图使用call调用oldfetch函数,并将url和options作为参数。但是,由于call只能一次传递一个参数,因此它将options视为单独的参数,而不是oldfetch函数的第二个参数。
相反,使用apply可以将参数作为数组传递,例如:
oldfetch.apply(this, ).then(response => {
// code
});

在这种情况下,oldfetch函数的参数被打包到一个数组中,并使用apply将它们传递给函数。
```


# 完整的Demo

返回response.text使用这个
```html
<!DOCTYPE html>
<html>
<head>
        <title>Custom Fetch Example</title>
        <meta charset="UTF-8">
</head>
<body>
        <h1>Custom Fetch Example</h1>
        <div id="result"></div>
        <script>
    let oldfetch = fetch;
    function fuckfetch() {
    return new Promise((resolve, reject) => {
    oldfetch.apply(this, arguments).then(response => {
    const oldJson = response.text;

    response.text = function() {
    return new Promise((resolve, reject) => {
    oldJson.apply(this, arguments).then(result => {
    console.log(result)
    resolve(result);
    });
    });
    };

    resolve(response);
    });
    });
    }
    fuckfetch('http://localhost:12600/ziji')
    .then(response => response.text())
    .then(data => {
    console.log(data);
    document.getElementById('result').innerText = JSON.stringify(data);
    })
    .catch(error => console.error(error));
        </script>
</body>
</html>
```

>随便找一个请求地址返回为text替换掉http://localhost:12600/ziji

返回response.json使用这个
```html
<!DOCTYPE html>
<html>

<head>
<title>Custom Fetch Example</title>
<meta charset="UTF-8">
</head>

<body>
<h1>Custom Fetch Example</h1>
<div id="result"></div>
<script>
    // 重新定义 fetch 函数
    let oldfetch = fetch;
    function fuckfetch() {
            return new Promise((resolve, reject) => {
                    oldfetch.apply(this, arguments).then(response => {
                            const oldJson = response.json;

                            response.json = function() {
                                    return new Promise((resolve, reject) => {
                                            oldJson.apply(this, arguments).then(result => {
                                                    result.hook = 'success';
                                                    resolve(result);
                                            });
                                    });
                            };

                            resolve(response);
                    });
            });
    }

    // 使用重写后的 fetch 进行请求
    fuckfetch('https://jsonplaceholder.typicode.com/todos/1')
            .then(response => response.json())
            .then(data => {
                    console.log(data);
                    document.getElementById('result').innerText = JSON.stringify(data);
            })
            .catch(error => console.error(error));
</script>
</body>

</html>
```

!(data/attachment/forum/202304/05/103524d8tg4mg22w4m9ia5.png)

wwwwwllllk 发表于 2023-4-5 12:56:16

xhr劫持:https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=1201

脚本体验师001 发表于 2023-4-5 13:12:32

哥哥的文章都是要看的,很有深度。哥哥代码写的好,不用问人都很帅气

wwwwwllllk 发表于 2023-4-5 13:34:07

脚本体验师001 发表于 2023-4-5 13:12
哥哥的文章都是要看的,很有深度。哥哥代码写的好,不用问人都很帅气
我也看哥哥的脚本学习了{:4_100:}

王一之 发表于 2023-4-5 14:54:10

这样好像没判断来源?什么fetch请求都会提示收藏成功

wwwwwllllk 发表于 2023-4-5 15:49:50

王一之 发表于 2023-4-5 14:54
这样好像没判断来源?什么fetch请求都会提示收藏成功

是的,这个只是大概写了一下,我暂时主要没有遇到类似的需求,实在是不想专门研究,太难了{:4_115:}
页: [1]
查看完整版本: Fetch劫持方式补充