首页 > 解决方案 > 正确格式化来自 VueJS 的身份验证请求对象

问题描述

我有一个使用 express/postgres api 的 VueJS/Vuex 前端。

在 Postman 中,注册和登录都使用如下请求:

{ "user": { "email": "user@gmail", "password":...}}

从 Vue 应用程序中,注册按预期工作,但用于登录,而不是发送请求对象,如

{ "user": { "email": "user@gmail", "password":...}}

,这是 api 所期望的,它只发送,

{ "email": "user@gmail", "password":...}

这导致 api 抛出:

TypeError:无法读取未定义的属性“电子邮件”

这是我的登录组件:

<template>
  <div class="ui stackable three column centered grid container">
    <div class="column">
      <h2 class="ui dividing header">Log In</h2>

      <Notification
        :message="notification.message"
        :type="notification.type"
        v-if="notification.message"
      />

      <form class="ui form" @submit.prevent="login">
        <div class="field">
          <label>Email</label>
          <input type="email" name="email" v-model="email" placeholder="Email" required>
        </div>

        <div class="field">
          <label>Password</label>
          <input type="password" name="password" v-model="password" placeholder="Password" required>
        </div>

        <button class="fluid ui primary button">LOG IN</button>

        <div class="ui hidden divider"></div>
      </form>

      <div class="ui divider"></div>

      <div class="ui column grid">
        <div class="center aligned column">
          <p>
            Don't have an account? <router-link to="/signup">Sign Up</router-link>
          </p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Notification from '@/components/Notification'
export default {
  name: 'LogIn',
  components: {
    Notification
  },
  data () {
    return {
      email: '',
      password: '',
      notification: {
        message: '',
        type: ''
      }
    }
  },
  // beforeRouteEnter (to, from, next) {
  //   const token = localStorage.getItem('tweetr-token')

  //   return token ? next('/') : next()
  // },
  methods: {
    login () {
      this.$store
        .dispatch('login', {
          email: this.email,
          password: this.password
        })
        .then(() => {
          console.log(this.$store.user)
          // redirect to user home
          this.$router.push('/')
        })
        .catch(error => console.log(error))
    }
  }
}
</script>

这是我的 store.js:

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

// import SubscriptionsService from './services/SubscriptionsService'

Vue.use(Vuex)
const VUE_APP_ROOT_API = 'http://localhost:8000'

export default new Vuex.Store({
  state: {
    status: '',
    user: JSON.parse(localStorage.getItem('user'))
  },
  mutations: {
    auth_request (state) {
      state.status = 'Signing in...'
    },
    set_user (state, user) {
      state.user = user
      localStorage.setItem('user', JSON.stringify(user))
      console.log(user)
    },
    auth_success (state) {
      state.status = 'success'
    },
    auth_error (state) {
      state.status = 'Invalid credentials'
    },
    logout (state) {
      state.status = ''
      state.user = null
      localStorage.removeItem('user')
    }
  },
  actions: {
    register ({ commit }, user) {
      return new Promise((resolve, reject) => {
        commit('auth_request')
        console.log(process.env.VUE_APP_ROOT_API)
        axios({ url: VUE_APP_ROOT_API + '/api/auth', data: user, method: 'POST' })
          .then(async resp => {
            const user = resp.data.user
            commit('auth_success')
            commit('set_user', user)
            resolve(resp)
          })
          .catch(err => {
            commit('auth_error', err)
            localStorage.removeItem('token')
            reject(err)
          })
      })
    },
    login ({ commit }, user) {
      return new Promise((resolve, reject) => {
        commit('auth_request')
        console.log(user);
        axios({ url: VUE_APP_ROOT_API + '/api/auth/login', data: user, method: 'POST' })
          .then(resp => {
            const user = resp.data.user
            // console.log(user)
            // console.log(resp)
            commit('auth_success')
            commit('set_user', user)
            resolve(resp)
          })
          .catch(err => {
            commit('auth_error')
            commit('logout')
            reject(err)
          })
      })
    },
    logout ({ commit }) {
      return new Promise((resolve) => {
        commit('logout')
        localStorage.removeItem('token')
        delete axios.defaults.headers.common['authorization']
        resolve()
      })
    }
  },
  getters: {
    isAuthenticated: state => !!state.user,
    authStatus: state => state.status,
    user: state => state.user
  }
})

为了比较,这是我的工作注册组件:

<template>
  <div class="ui stackable three column centered grid container">
    <div class="column">
      <h2 class="ui dividing header">Sign Up, it's free!</h2>

      <form class="ui form" @submit.prevent="signup">

        <div class="field">
          <label>Username</label>
          <input type="username" name="username" v-model="username" placeholder="Username">
        </div>

        <div class="field">
          <label>Email</label>
          <input type="email" name="email" v-model="email" placeholder="Email">
        </div>

        <div class="field" >
          <label>Password</label>
          <input type="password" name="password" v-model="password" placeholder="Password">
        </div>

        <button class="fluid ui primary button">SIGN UP</button>

        <div class="ui hidden divider"></div>
      </form>

      <div class="ui divider"></div>

      <div class="ui column grid">
        <div class="center aligned column">
          <p>
            Got an account? <router-link to="/login">Log In</router-link>
          </p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>

export default {
  name: 'SignUp',
  data () {
    return {
      email: '',
      password: '',
      username: '',
      notification: {
        message: '',
        type: ''
      }
    }
  },
  methods: {
    signup: function () {
      let data = {
        user: {
          email: this.email,
          password: this.password,
          username: this.username
        }
      }
      this.$store.dispatch('register', data)
        .then(() => this.$router.push('/'))
        .catch(err => console.log(err))
    },
  }
}
</script>

如何格式化请求对象以匹配 api 的期望?

标签: expressauthenticationvue.jsvuex

解决方案


尝试以与您的注册功能类似的结构发送有效负载:

 .dispatch('login', { 
   user: {
     email: this.email,
     password: this.password
   }
})

推荐阅读