简体   繁体   English

Express.js Csurf 在邮递员工作但不是 React.js

[英]Express.js Csurf working in postman but not React.js

I'm trying to setup CSRF tokens so that I can do a number of checks before issueing a token to the client to use in future requests.我正在尝试设置 CSRF 令牌,以便在向客户端发出令牌以在将来的请求中使用之前可以进行一些检查。

Taking the guidance from the csurf documentation , I've setup my express route with the following:从 csurf文档中获取指导,我已经使用以下内容设置了我的快速路线:

const express = require('express');
const router = express.Router({mergeParams: true});
const csurf = require('csurf');
const bodyParser = require('body-parser');
const parseForm = bodyParser.urlencoded({ extended: false });

const ErrorClass = require('../classes/ErrorClass');

const csrfMiddleware = csurf({
    cookie: true
});

router.get('/getCsrfToken', csrfMiddleware, async (req, res) => {
    try {
        // code for origin checks removed for example
        return res.json({'csrfToken': req.csrfToken()});
    } catch (error) {
        console.log(error);
        return await ErrorClass.handleAsyncError(req, res, error);
    }
});

router.post('/', [csrfMiddleware, parseForm], async (req, res) => {
    try {
        // this returns err.code === 'EBADCSRFTOKEN' when sending in React.js but not Postman
    } catch (error) {
        console.log(error);
        return await ErrorClass.handleAsyncError(req, res, error);
    }
});

For context, the React.js code is as follows, makePostRequest 100% sends the _csrf token back to express in req.body._csrf对于上下文,React.js 代码如下, makePostRequest 100% 将_csrf令牌发回req.body._csrf表达

  try {
            const { data } = await makePostRequest(
                CONTACT,
                {
                    email: values.email_address,
                    name: values.full_name,
                    message: values.message,
                    _csrf: csrfToken,
                },
                { websiteId }
            );

        } catch (error) {
            handleError(error);
            actions.setSubmitting(false);
        }

Postman endpoint seems to be sending the same data, after loading the /getCsrfToken endpoint and I manually update the _csrf token.在加载/getCsrfToken端点并且我手动更新_csrf令牌后,邮递员端点似乎正在发送相同的数据。

邮递员例子

Is there something I'm not doing correctly?有什么我做错了吗? I think it may be to do with Node.js's cookie system.我认为这可能与 Node.js 的 cookie 系统有关。

I think your problem is likely to be related to CORS (your dev tools will probably have sent a warning?).我认为您的问题可能与 CORS 相关(您的开发工具可能会发出警告?)。

Here's the simplest working back-end and front-end I could make, based on the documentation:根据文档,这是我可以制作的最简单的后端和前端工作:

In Back-End (NodeJS with Express) Server:在后端(带有 Express 的 NodeJS)服务器中:

In app.js:在 app.js 中:

var cookieParser = require('cookie-parser')
var csrf = require('csurf')
var bodyParser = require('body-parser')
var express = require('express')
const cors = require('cors');

var csrfProtection = csrf({ cookie: true })
var parseForm = bodyParser.urlencoded({ extended: false })

var app = express()

const corsOptions = {
  origin: "http://localhost:3000",
  credentials: true,
}
app.use(cors(corsOptions));

app.use(cookieParser())

app.get('/form', csrfProtection, function (req, res) {
  res.json({ csrfToken: req.csrfToken() })
})

app.post('/process', parseForm, csrfProtection, function (req, res) {
  res.send('data is being processed')
})

module.exports = app;

(make sure you update the corsOptions origin property to whatever your localhost is in React. (确保将corsOptions origin属性更新为 React 中的任何本地主机。

In Index.js:在 Index.js 中:

const app = require('./app')

app.set('port', 5000);

app.listen(app.get('port'), () => {
    console.log('App running on port', app.get('port'));
});

In React:在反应中:

Create file "TestCsurf.js" and populate with this code:创建文件“TestCsurf.js”并使用以下代码填充:

    import React from 'react'
    
    export default function TestCsurf() {
    
        let domainUrl = `http://localhost:5000`
        const [csrfTokenState, setCsrfTokenState] = React.useState('')
        const [haveWeReceivedPostResponseState, setHaveWeReceivedPostResponseState] = React.useState("Not yet. No data has been processed.")
    
        async function getCallToForm() {
            const url = `/form`;
            let fetchGetResponse = await fetch(`${domainUrl}${url}`, {
                method: "GET",
                headers: {
                    Accept: "application/json",
                    "Content-Type": "application/json",
                    "xsrf-token": localStorage.getItem('xsrf-token'),
                },
                credentials: "include",
                mode: 'cors'
            })
            let parsedResponse = await fetchGetResponse.json();
            setCsrfTokenState(parsedResponse.csrfToken)
        }
    
        React.useEffect(() => {
            getCallToForm()
        }, [])
    
        async function testCsurfClicked() {
            const url = `/process`
            let fetchPostResponse = await fetch(`${domainUrl}${url}`, {
                method: "POST",
                headers: {
                    Accept: "application/json",
                    "Content-Type": "application/json",
                    "xsrf-token": csrfTokenState,
                },
                credentials: "include",
                mode: 'cors',
            })
            let parsedResponse = await fetchPostResponse.text()
            setHaveWeReceivedPostResponseState(parsedResponse)
        }
    
        return (
            <div>
                <button onClick={testCsurfClicked}>Test Csurf Post Call</button>
                <p>csrfTokenState is: {csrfTokenState}</p>
                <p>Have we succesfully navigates csurf with token?: {JSON.stringify(haveWeReceivedPostResponseState)}</p>
            </div>
        )
    }

Import this into your app.js将其导入您的 app.js

import CsurfTutorial from './CsurfTutorial';

function App() {
  return (
    <CsurfTutorial></CsurfTutorial>
  );
}

export default App;

That's the simplest solution I can make based on the CSURF documentations example.这是我可以根据 CSURF 文档示例做出的最简单的解决方案。 It's taken me several days to figure this out.我花了好几天才弄清楚这一点。 I wish they'd give us a bit more direction!我希望他们能给我们更多的方向!

I made a tutorial video in case it's of any help to anyone: https://youtu.be/N5U7KtxvVto我制作了一个教程视频,以防对任何人有帮助: https : //youtu.be/N5U7KtxvVto

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM