【问题标题】:Not able to access token using axios and djangorestframework-jwt无法使用 axios 和 djangorestframework-jwt 访问令牌
【发布时间】:2019-04-15 05:33:01
【问题描述】:

我正在尝试通过 django rest 框架创建一个服务器 api 的应用程序,前端在 vue.js2 中完成。

我指的是this blog 帮助我通过 axios 验证 jwt。当我无法正确运行第一个时,我也尝试了this one

这是我的 settings.py 文件

INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework.authtoken',
    'admindash',
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser',
    ),
    'TEST_REQUEST_RENDERER_CLASSES': (
        'rest_framework.renderers.MultiPartRenderer',
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.TemplateHTMLRenderer'
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 20,
}

JWT_AUTH = {
    'JWT_ALLOW_REFRESH': True,
    'JWT_EXPIRATION_DELTA': timedelta(hours=1),
    'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=7),
}

#Cors origin
CORS_ORIGIN_WHITELIST = (
    'localhost:8080'
)
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

这是我的 vue 商店

axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'

export default new Vuex.Store({
  state: {
    authUser: {},
    isAuthenticated: false,
    jwt: localStorage.getItem('token'),
    endpoints: {
      obtainJWT: 'http://127.0.0.1:8000/api/v1/auth/obtain_token/',
      refreshJWT: 'http://127.0.0.1:8000/api/v1/auth/refresh_token/',
      baseUrl: 'http://127.0.0.1:8000/api/v1'
    }
  },

  mutations: {
    setAuthUser(state, {
      authUser,
      isAuthenticated
    }) {
      Vue.set(state, 'authUser', authUser)
      Vue.set(state, 'isAuthenticated', isAuthenticated)
    },
    updateToken(state, newToken) {
      localStorage.setItem('token', newToken);
      state.jwt = newToken;
    },
    removeToken(state) {
      localStorage.removeItem('token');
      state.jwt = null;
    }
  },

  actions: {
    obtainToken(context, {username, password}) {
      const payload = {
        username: username,
        password: password
      }
      const headers= {
        'Content-Type': 'application/json'
      }

      axios.post(this.state.endpoints.obtainJWT, headers, payload)
        .then((response) => {
          this.commit('updateToken', response.data.token);
          console.log(this.state.jwt);
        })
        .catch((error) => {
          console.log(error);
        })
    },

    refreshToken () {
      const payload = {
        token: this.state.jwt
      }

      axios.post(this.state.endpoints.refreshJWT, payload)
        .then((response) => {
          this.commit('updateToken', response.data.token);
          console.log(this.state.jwt)
        })
        .catch((error) => {
          console.log(error)
        })
    }
  }
})

这里是 login.vue

<script>
import axios from 'axios'
import FormInput from './FormInput'

export default {
  name: 'Login',
  components: {
    FormInput
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  computed: {
    /* ...mapState([
      'jwt',
      'endpoints'
    ]) */
  },
  methods: {
    /* ...mapActions([
      'obtainToken'
    ]), */

    authenticateBeforeSubmit () {
      this.$store.dispatch('obtainToken', {
        username: this.username,
        password: this.password
      }).then(() => {
        this.$router.push('/')
      }).catch((error) => {
        console.log(error)
      })

      /* const payload = {
        username: this.username,
        password: this.password
      }
      axios.post(this.$store.state.endpoints.obtainJWT, payload)
        .then((response) => {
          this.$store.commit('updateToken', response.data.token)
          console.log(this.$store.state.jwt);
          const base = {
            baseUrl: this.$store.state.endpoints.baseUrl,
            headers: {
              Authorization: `JWT ${this.$store.state.jwt}`,
              'Content-Type': 'application/json'
            },
            xhrFields: {
              withCredentials: true
            }
          }

          const axiosInstance = axios.create(base)
          axiosInstance({
            url: "/user/",
            method: "get",
            params: {}
          })
            .then((response) => {
              this.$store.commit("setAuthUser", 
              {authUser: response.data, isAuthenticated: true}
              )
              this.$router.push({name: 'Home'})
            })
        })
        .catch((error) => {
          console.log(error);
          console.debug(error);
          console.dir(error);
        }) */
    }
  }
}
</script>

现在的问题是我遇到了两个错误

  1. 当我在浏览器中加载登录视图时,我得到了这个错误

    Uncaught (in promise) TypeError: Cannot read property 'protocol' of undefined 在 isURLSameOrigin (VM34519 isURLSameOrigin.js:57) 在 dispatchXhrRequest (VM34513 xhr.js:109) 在新的承诺 () 在 xhrAdapter (VM34513 xhr.js:12) 在 dispatchRequest (VM34521 dispatchRequest.js:59) isURLSameOrigin @ VM34519 isURLSameOrigin.js:57 dispatchXhrRequest@VM34513 xhr.js:109 xhrAdapter@VM34513 xhr.js:12 dispatchRequest@VM34521 dispatchRequest.js:59 18:29:09.976

我完全不知道这个错误是关于什么的,我搜索了它,但没有找到任何有效的方法

  1. 当我单击提交时会触发 authenticateBeforeSubmit 方法时得到这个

    未捕获的类型错误:无法读取未定义的属性“调度” 在 VueComponent.authenticateBeforeSubmit (VM34576 Login.vue:68) 在调用者处 (VM34494 vue.esm.js:2026) 在 HTMLButtonElement.fn._withTask.fn._withTask (VM34494 vue.esm.js:1825) authenticateBeforeSubmit@VM34576 Login.vue:68 调用者@VM34494 vue.esm.js:2026 fn._withTask.fn._withTask@VM34494 vue.esm.js:1825 18:29:30.912

我的理解是说我错误地调用了动作调度,但我不知道如何使它工作

当我点击提交时,它“重定向”到

http://127.0.0.1:8080/login?username=f1uk3r&password=thisissparta

但它没有收到任何令牌

我已经使用

测试了令牌
curl -X POST -H "Content-Type: application/json" -d '{"username":"f1uk3r","password":"thisissparta"}' http://127.0.0.1:8000/api/v1/auth/obtain_token/

它给了我一个令牌,所以我认为 django 部分应该没有任何问题。我做错了什么,我该如何纠正。

【问题讨论】:

    标签: vue.js axios django-rest-framework-jwt


    【解决方案1】:

    我想通了,所以回答以供将来参考,如果其他人觉得这很有用

    1. TypeError:无法读取 isURLSameOrigin 处未定义的属性“协议”

    这个可以通过正确导入axios和VueAxios来解决

    我是这样初始化的

    import Vue from 'vue'
    import VueAxios from 'vue-axios'
    import Vuex from 'vuex'
    import axios from 'axios'
    
    Vue.use(Vuex);
    Vue.use(axios, VueAxios);
    

    虽然它应该像这样初始化

    import Vue from 'vue'
    import VueAxios from 'vue-axios'
    import Vuex from 'vuex'
    import axios from 'axios'
    
    Vue.use(Vuex);
    Vue.use(VueAxios, axios);
    
    1. 无法读取 VueComponent 中未定义的属性 'dispatch'

    再次,我没有正确初始化 store,所以我在“src”目录中创建了一个目录,命名为“store”,并在这个目录中创建了一个名为“store.js”的文件

    然后在main.js中导入存储并在实例中初始化

    import store from './store/store.js';
    
    
    Vue.use(VeeValidate);
    
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      store,
      components: { App },
      template: '<App/>'
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 2021-02-12
      • 2021-08-23
      • 2019-12-08
      • 2021-02-13
      相关资源
      最近更新 更多