Vue+Django CORS and CSRF

Backend (Django) Part

Docs: django-cors-headers, django core settings

According to django-cors-headers, use:

1
python -m pip install django-cors-headers

to install django-cors-headers and add it to installed apps in settings.py

1
2
3
4
5
INSTALLED_APPS = [
...,
"corsheaders",
...,
]

Add a middleware class to listen in on responses. The order of middlewares is important:

CorsMiddleware should be placed as high as possible, especially before any middleware that can generate responses such as Django’s CommonMiddleware or Whitenoise’s WhiteNoiseMiddleware. If it is not before, it will not be able to add the CORS headers to these responses.

Also if you are using CORS_REPLACE_HTTPS_REFERER it should be placed before Django’s CsrfViewMiddleware.

1
2
3
4
5
6
MIDDLEWARE = [
...,
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
...,
]

Assume frontend is functioning on frontend.com.

Add:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CORS_ALLOWED_ORIGINS = [
"frontend.com",
]

CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
#enable whatever method needed
]

CSRF_TRUSTED_ORIGINS = [
"frontend.com",
]

CORS_ALLOW_CREDENTIALS = True

CSRF_COOKIE_SECURE = True

CSRF_COOKIE_SAMESITE = 'None'

Frontend (Vue) Part

Docs: Axios Request Config

We need to get CSRF token contained in cookie from backend.

In urls.py:

1
2
3
4
5
6
7
8
9
def get_csrf_token(request):
csrf_token = get_token(request)
return JsonResponse({'token': csrf_token})

urlpatterns=[
...
path('get_csrf_token/', get_csrf_token),
...
]

Assume the backend is functioning on backend.com. In whateverName.vue, add:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//django use cookies to varify csrf
import VueCookies from 'vue-cookies'
Vue.use(VueCookies)
//`withCredentials` indicates whether or not cross-site Access-Control requests should be made using credentials
axios.defaults.withCredentials = true

export default{
data(){
return{
token:'',
}
},
methods:{
//get token function
gettoken() {
axios({
method: 'get',
url: `http://backend.com/get_csrf_token/`,
withCredentials: true
})
.then((res) => {
this.token = res.data.token
})
},
//POST
tryPOST(){
axios({
headers: {
'X-CSRFToken': this.token,
'Content-Type': 'application/json',
},
withCredentials: true,
url: `http://backend.com/whateverURL`,
method: 'post',
data: {
'data1': 'data2',
}
})
.then((res) => {
console.log(res)
})
}
},
mounted:()=>{
//get token when page loads
this.gettoken()
}
}