第一步跨域配置(注意配置位置):
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hh.apps.HhConfig',
'rest_framework',
'corsheaders',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
]
# 跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = ()
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'X-CSRFToken'
)
这时候你会惊奇的发现一个令人头大的问题,what?怎么?
Post这个龟儿子 给你返回了:
Forbidden (403)
CSRF verification failed. Request aborted.
如果报错和博主一样,切记不要先砸电脑,你遇到了我,让我来拯救你吧!!
第二步先来看一下问题出现的原因:
在客户端页面上添加csrftoken, 服务器端进行验证,服务器端验证的工作通
过'django.middleware.csrf.CsrfViewMiddleware'这个中间层来完成。在django当中防御csrf攻击
的方式有两种, 1.在表单当中附加csrftoken 2.通过request请求中添加X-CSRFToken请求头。注
意:Django默认对所有的POST请求都进行csrftoken验证,若验证失败则403错误侍候。
第三步解决这个龟儿子的问题:
写什么写,直接上代码
后端获取token代码:
def get_csrf_token(request):
token = django.middleware.csrf.get_token(request)
return JsonResponse({'token': token})
后端登录代码:
def getloginvalidate(request):
print(request.headers)
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user_infos = UserInfo.objects.filter(username=username,password=password)
token = django.middleware.csrf.get_token(request)
if user_infos.exists():
return JsonResponse({'code': 'OK','username':username,'password':password,'token': token})
else:
return JsonResponse({'code': 'NO'})
if request.method == 'GET':
return JsonResponse({'code': 'get'})
前端代码:
Home.vue
<template>
<div class="home">
<HelloWorld/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import {getCSRFtoken} from '@/network/login'
export default {
name: 'Home',
components: {
HelloWorld
},
created() {
//初始化token,存入缓存
getCSRFtoken().then(res => {
this.$store.commit('setCSRFToken',res.data.token)
})
},
}
</script>
HelloWorld.vue
<template>
<div class="hello">
<div class="input_warp">
<label for="username">用户名 </label>
<div class="inner">
<el-input id="username" placeholder="请输入用户名" v-model="username" clearable/>
</div>
</div>
<div class="input_warp">
<label for="password"> 密 码 </label>
<div class="inner">
<el-input id="password" placeholder="请输入密码" v-model="password" show-password/>
</div>
</div>
<div class="btncls">
<el-button type="primary" @click="login">登录</el-button>
</div>
</div>
</template>
<script>
import {getloginvalidate, testapi} from '@/network/login'
export default {
name: 'HelloWorld',
data() {
return {
username: '',
password: ''
}
},
methods: {
login() {
if (this.username.length == 0 && this.password.length == 0) {
this.$alert('用户名和密码不能为空', '提示', {
confirmButtonText: '确定',
});
} else {
getloginvalidate(this.username, this.password).then(res => {
console.log(res);
if (res.data.code == 'OK'){
// 跳转到详情页
this.$router.replace('/about');
this.$store.commit('setLogin');
this.$store.commit('setCSRFToken',res.data.token);
}
})
}
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
width: 80%;
margin: 30% auto 10px;
}
.input_warp {
margin: 10px 0;
}
.inner {
width: 80%;
display: inline-block;
}
.btncls {
margin: 20px;
}
label {
display: inline-block;
width: 20%;
}
</style>
login.js
import {request} from './request';
export function getloginvalidate(username,password) {
let params = new URLSearchParams();
params.append('username',username);
params.append('password',password);
return request({
url: '/getloginvalidate/',
method:'POST',
data:params,
})
}
export function getCSRFtoken() {
return request({
url: '/get-token/',
method: 'get'
})
}
request.js
import axios from 'axios'
import store from '@/store';
axios.defaults.withCredentials = true; //跨域访问需要发送cookie时一定要加
export function request(config) {
const instance = axios.create({
baseURL: 'http://10.40.4.8:8000',
timeout: 5000
});
instance.interceptors.request.use(config => {
if (config.method === 'post'){
config.headers['X-CSRFToken'] = store.state.CSRFToken;
}
return config
}, err => {
return err
});
instance.interceptors.response.use(res => {
return res
}, err => {
return err
});
return instance(config)
}