Golang CSRF 问题与 React

Golang CSRF issues with React

我正在创建一个与用 Go 编写的后端对话的 React 应用程序。我已经使用 Gorilla 库设置了 CSRF。 React 代码将首先向接收令牌的 csrfToken 端点发送 GET 请求。此令牌在发送 POST 请求时在 header 中设置。

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/signup/post", SubmitSignupForm).Methods(http.MethodPost, http.MethodOptions)
    r.HandleFunc("/csrfToken", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(csrf.Token(r)))
    })

    r.Use(csrf.Protect(
        []byte("fff"),
        csrf.Path("/"),
        csrf.Secure(false),
        csrf.TrustedOrigins([]string{"http://localhost:3001/"}),
        csrf.RequestHeader("TOKEN"),
    ))

    c := cors.AllowAll()

    http.ListenAndServe(":8000", c.Handler(r))
}

React 代码如下所示:

import React from 'react';
import './App.css';
import useAxios from "axios-hooks";

function App() {
    const [{response: csrfToken}] = useAxios<string>({url: "http://localhost:8000/csrfToken"})
    const [{response}, doRequest] = useAxios<string>({
        url: "http://localhost:8000/signup/post",
        method: "POST"
    }, {manual: true})

    return (
        <div className="App">
            <header className="App-header">
                <h1>hello</h1>
                <h1>csrf: {csrfToken?.data}</h1>
                <h1>Response: {response?.data}</h1>
                <button onClick={e => {
                    doRequest({data: {key: "something"}, headers: {"TOKEN": csrfToken!.data}})

                }}>click
                </button>
            </header>
        </div>
    );
}

export default App;

让我最困惑的是我能够使用 Postman 将请求发送到 /csrfToken 端点并将该值与 header.

一起使用

但是,当我在浏览器中执行相同操作时,我收到 403 并响应 Forbidden - CSRF token invalid

知道我做错了什么吗?

我不熟悉 axios-hooks,但是你不想在你的 React 代码中执行 csrf 函数并像使用 doRequest() 那样获取 CSRF 令牌吗? 没有第二个 属性 在 csrf 中被解构,就像在 doRequest() 中一样。

如果在没有第二个 属性 的情况下执行 csrf 函数会执行 axios 函数,您可能需要一个 await 或 .then 链,因为它可能 returns 一个承诺。

我认为这个问题可能比 Go 更适合 React,我觉得还不错。

我想通了。

我通过首先创建一个设置简单得多的虚拟项目来开始调试应用程序。在那里我成功地设置了一切。在了解这两个应用程序的差异时,我注意到 cookie 没有在不工作的应用程序中发送。

一段时间后,我了解到由于跨源,cookie 没有从浏览器发送到 API。所有这些都是 运行 本地的,我痛苦的错误是:

localhost != 127.0.0.1

我需要做的就是将所有使用 localhost 的地方更改为 127.0.0.1。由于浏览器认为两者来源不同,不会发送cookies...