[英]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:根据文档,这是我可以制作的最简单的后端和前端工作:
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 中的任何本地主机。
const app = require('./app')
app.set('port', 5000);
app.listen(app.get('port'), () => {
console.log('App running on port', app.get('port'));
});
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 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.