VueJS и экспресс-токен csrf для публикации - PullRequest
0 голосов
/ 06 января 2019

Я использую 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 Ответ

0 голосов
/ 13 января 2019

Мне нужно было правильно передать заголовочные файлы 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();
});
...
...