VueJS 和 express 传递 csrf 令牌发布

Posted

技术标签:

【中文标题】VueJS 和 express 传递 csrf 令牌发布【英文标题】:VueJS and express pass csrf token to post 【发布时间】:2019-06-01 14:38:16 【问题描述】:

我在后端使用 VueJS (cli 3) & axios,以及 NodeJS - ExpressJS。我正在尝试使用 CSRF 令牌保护我的帖子用户编辑。

Vue 视图(编辑用户 - 关注 mySubmitEd):

<template>
  <div class="one-user">
    <h1>this user</h1>
    <h2>name - surname -  perm </h2>
    <h2>Edit</h2>
    <input type="text" v-model="name">
    <input type="text" v-model="surname">
    <input type="text" v-model="perm">
    <button @click="mySubmitEd">Edit</button>
    <button @click="mySubmit">Delete</button>
  </div>
</template>

<script>
import axios from 'axios'
import io from 'socket.io-client'
export default 
  name: 'one-user',
  data () 
    return 
      name: '',
      surname: '',
      perm: '',
      csrf: '',
      id: this.$route.params.id,
      socket: io('localhost:7000')
    
  ,
  mounted () 
    axios.get('http://localhost:7000/api/get-user/' + this.id)
      .then(res => 
        const data = res.data.user
        this.name = data.name
        this.surname = data.last_name
        this.perm = data.permalink
        this.csrf = res.data.csrfToken
        axios.defaults.headers.common['X-CSRF-TOKEN'] = this.csrf
      )
      .catch(error => console.log(error))
  ,
  methods: 
    mySubmit () 
      const formData = 
        _id: this.id
      
      axios.post('http://localhost:7000/api/delete-user', formData)
        .then(this.$router.push( name: 'get-user' ))
        .catch(error => console.log(error))
    ,
    mySubmitEd () 
      const formData = 
        _id: this.id,
        name: this.name,
        last_name: this.surname,
        permalink: this.perm,
        _csrf: this.csrf
      
      console.log(formData._csrf)
      axios.post('http://localhost:7000/api/update-user', formData)
        .catch(error => console.log(error))
    
  

</script>

server.js 文件:

...
const cookieParser  = require('cookie-parser');
const csurf         = require('csurf');
...
app.use(cookieParser());
const csrfProtection = csurf( cookie: true );
app.use(csrfProtection);
...

获取用户的后端控制器:

controller.getOneUser = function(req, res) 
  User.findOne( _id: req.params.userId ).exec(function(err, user) 
    res.json(user, csrfToken: req.csrfToken());
  );
;

后台更新帖:

controller.updateUser = function(req, res) 
  User.findById(req.body._id, function(err, user) 
    user.set(
      name: req.body.name,
      last_name: req.body.last_name,
      permalink: req.body.permalink,
      price: req.body.price
    );
    user.save();
    res.send(user);
  );
;

我在 NodeJS-exress 控制台中的错误:

ForbiddenError: invalid csrf token

我在浏览器中的错误:

POST http://localhost:7000/api/update-user 403 (Forbidden)

我不知道发生了什么,因为我在网络选项卡(chrome)中看到 csrf 令牌在标题和我发送的内容(例如)中是相同的:

X-CSRF-TOKEN: PddyOZrf-AdHppP3lMuWA2n7AuD8QWFG3ta0
_csrf: "PddyOZrf-AdHppP3lMuWA2n7AuD8QWFG3ta0"

我不知道我在这里想念什么。我找不到问题出在哪里。

如果您想了解更多信息,请让我帮助您。

【问题讨论】:

【参考方案1】:

我必须正确传递 cookie 的标题,所以我做了 2 处更正:

Vue 视图中的第一个:

我通过了凭据:

axios.create(withCredentials: true).get(...)

axios.create(withCredentials: true).post(...)

其次,在路由之前的 server.js 文件中,我放了这个:

...
const corsOptions = 
    origin: 'http://localhost:8080',
    credentials: true,

app.use(cors(corsOptions));

app.use(bodyParser.json());
app.use(cookieParser());
const csrfProtection = csurf( cookie: true );
app.use(csrfProtection);

app.use(function (req, res, next) 
    res.cookie('XSRF-TOKEN', req.csrfToken());     
    res.locals._csrf = req.csrfToken();
    next();
);
...

【讨论】:

以上是关于VueJS 和 express 传递 csrf 令牌发布的主要内容,如果未能解决你的问题,请参考以下文章

如何在 VueJS 文件中添加 Laravel CSRF 令牌? [复制]

VueJs 前端的无效 CSRF 令牌错误(symfony 5)

将它们分开时将 Django 的 csrf_token 放入 Vuejs

CSRF 令牌不匹配错误,Laravel 5.3/VueJS2

如何在 vuejs 组件中使用 laravel csrf 令牌

在 laravel+vuejs 项目中允许 X-CSRF-TOKEN 吗?