本文介绍了Express.js Csurf在邮递员中工作,但不在React.js中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置CSRF令牌,以便在向客户端颁发令牌以用于将来的请求之前可以进行多次检查.

按照csurf的指导

有什么我做不正确的事情吗?我认为这可能与Node.js的cookie系统有关.

解决方案

我认为您的问题很可能与CORS有关(您的开发工具可能已发出警告?).

根据文档,这是我能制作的最简单的后端和前端:

在后端(带有Express的NodeJS)服务器中:

在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({扩展:false})var app = express()const corsOptions = {来源:"http://localhost:3000",凭据:是的,}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('数据正在处理')})module.exports =应用程序; 

(确保将 corsOptions origin 属性更新为React中的本地主机.

在Index.js中:

  const app = require('./app')app.set('port',5000);app.listen(app.get('port'),()=> {console.log('App在端口上运行',app.get('port'));}); 

在React中:

创建文件"TestCsurf.js";并填充以下代码:

 从'react'导入React导出默认函数TestCsurf(){让domainUrl =`http://localhost:5000`const [csrfTokenState,setCsrfTokenState] = React.useState('')const [haveWeReceivedPostResponseState,setHaveWeReceivedPostResponseState] = React.useState(尚未.尚未处理任何数据.")异步函数getCallToForm(){const url =`/form`;让fetchGetResponse =等待fetch(`$ {domainUrl} $ {url}`,{方法:"GET",标头:{接受:"application/json","Content-Type":"application/json","xsrf-token":localStorage.getItem('xsrf-token'),},凭据:包括",模式:"cors"})让parsedResponse =等待fetchGetResponse.json();setCsrfTokenState(parsedResponse.csrfToken)}React.useEffect(()=> {getCallToForm()},[])异步功能testCsurfClicked(){const url =`/process`let fetchPostResponse =等待fetch(`$ {domainUrl} $ {url}`,{方法:"POST",标头:{接受:"application/json","Content-Type":"application/json","xsrf-token":csrfTokenState,},凭据:包括",模式:"cors",})让parsedResponse =等待fetchPostResponse.text()setHaveWeReceivedPostResponseState(parsedResponse)}返回 (< div>< button onClick = {testCsurfClicked}>测试Csurf发布呼叫</button>< p> csrfTokenState是:{csrfTokenState}</p>< p>我们是否已成功使用令牌导航csurf ?: {JSON.stringify(haveWeReceivedPostResponseState)}</p></div>)} 

将其导入到您的app.js

 从'./CsurfTutorial'导入CsurfTutorial;函数App(){返回 (< CsurfTutorial></CsurfTutorial>);}导出默认应用程序; 

根据CSURF文档示例,这是我可以做的最简单的解决方案.我花了几天的时间才弄清楚.希望他们能给我们更多的指导!

我制作了一个教程视频,以防对任何人有帮助: https://youtu.be/N5U7KtxvVto

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.

Taking the guidance from the csurf documentation, I've setup my express route with the following:

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

  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.

Is there something I'm not doing correctly? I think it may be to do with Node.js's cookie system.

解决方案

I think your problem is likely to be related to CORS (your dev tools will probably have sent a warning?).

Here's the simplest working back-end and front-end I could make, based on the documentation:

In Back-End (NodeJS with Express) Server:

In 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.

In 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:

    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

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. 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

这篇关于Express.js Csurf在邮递员中工作,但不在React.js中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 13:23