无法使用 axios 和 djangorestframework-jwt 访问令牌
Not able to access token using axios and djangorestframework-jwt
我正在尝试通过 django rest 框架制作一个服务器 api 的应用程序,前端是在 vue.js2 中完成的。
我指的是 this blog to help me authenticating jwt via axios. I also tried 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>
现在的问题是我遇到了两个错误
当我在浏览器中加载登录视图时,出现此错误
未捕获(承诺)类型错误:无法读取未定义的 属性 'protocol'
在 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
我完全不知道这个错误是怎么回事,我搜索了一下,但没有找到任何有用的东西
这是我在点击提交时得到的,这会触发 authenticateBeforeSubmit 方法
Uncaught TypeError: 无法读取未定义的 属性 'dispatch'
在 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@VM34494vue.esm.js:1825
18:29:30.912
我的理解是我错误地调用了 dispatch on action 但我不知道如何让它工作
当我点击提交时 "redirects" 到
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 部分应该没有任何问题。我做错了什么,我该如何纠正。
我明白了,所以回答以供将来参考,如果其他人觉得这有用
- TypeError: 无法读取 isURLSameOrigin
处未定义的 属性 'protocol'
正确导入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);
- 无法读取 VueComponent
未定义的 属性 'dispatch'
同样,我没有正确初始化存储,所以我在 "src" 目录中创建了一个名为 "store" 的目录,并在该目录中创建了一个名为 "store.js"[=13= 的文件]
然后在main.js实例中导入store并初始化
import store from './store/store.js';
Vue.use(VeeValidate);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
我正在尝试通过 django rest 框架制作一个服务器 api 的应用程序,前端是在 vue.js2 中完成的。
我指的是 this blog to help me authenticating jwt via axios. I also tried 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>
现在的问题是我遇到了两个错误
当我在浏览器中加载登录视图时,出现此错误
未捕获(承诺)类型错误:无法读取未定义的 属性 'protocol' 在 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
我完全不知道这个错误是怎么回事,我搜索了一下,但没有找到任何有用的东西
这是我在点击提交时得到的,这会触发 authenticateBeforeSubmit 方法
Uncaught TypeError: 无法读取未定义的 属性 'dispatch' 在 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@VM34494vue.esm.js:1825 18:29:30.912
我的理解是我错误地调用了 dispatch on action 但我不知道如何让它工作
当我点击提交时 "redirects" 到
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 部分应该没有任何问题。我做错了什么,我该如何纠正。
我明白了,所以回答以供将来参考,如果其他人觉得这有用
- TypeError: 无法读取 isURLSameOrigin 处未定义的 属性 'protocol'
正确导入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);
- 无法读取 VueComponent 未定义的 属性 'dispatch'
同样,我没有正确初始化存储,所以我在 "src" 目录中创建了一个名为 "store" 的目录,并在该目录中创建了一个名为 "store.js"[=13= 的文件]
然后在main.js实例中导入store并初始化
import store from './store/store.js';
Vue.use(VeeValidate);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})