简体   繁体   中英

How can I get the Cookies' `csrftoken` in `Axios.interceptors.request`'s config?

How can I get the Cookies' csrftoken in Axios.interceptors.request 's config?

Axios.interceptors.request.use(
  config => {

    if (
      config.method === "post" ||
      config.method === "put" ||
      config.method === "delete"||
      config.method === "get"
    ) {

    }


    if (Cookies.get('token')!==undefined) {   
      config.headers['Authorization']= 'Token '+Cookies.get('token');
    }
    // there I try to get the `csrftoken` in the Cookies, but I can not get.
    if (Cookies.get('csrftoken')!==undefined) {   

      config.headers['x-csrftoken']= Cookies.get('csrftoken');  // 'CSRFToken'
    }

    return config;
  },
  error => {  
    return Promise.reject(error.data.error.message);
  }
);

In the Axios.interceptors.request 's config I can not get Cookies's csrftoken : Cookies.get('csrftoken') .

my AxiosConfig code is bellow:

AxiosConfig:{
    baseURL: 'http://10.10.10.105:8001/',

    responseType: "json",
    withCredentials: true,  // there will send the Cookie (with it there are: sessionid, csrftoken)

    xsrfCookieName: 'csrftoken',  // default: XSRF-TOKEN
    xsrfHeaderName: 'x-csrftoken',   // default: X-XSRF-TOKEN
    headers: {
      "Content-Type": "application/json;charset=utf-8"
    }
  }

edit-1

There is the csrftoken in the Cookie.

在此处输入图片说明


edit-2

And in the cookie, there is no csrftoken too.

在此处输入图片说明


edit-3

if I get the document.cookie in console, I will get the "" : ```

document.cookie
< "" ```


edit-4

in my Django backend, the settings.py :

INSTALLED_APPS:

...
'corsheaders', 

'rest_framework',
'rest_framework.authtoken',
'rest_framework_docs',   
'rest_auth',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_auth.registration',
...

I am not sure whether the rest_auth and allauth will affect the csrftoken .

First of all, always make sure that the cookie is not flagged as httpOnly .

If it is, your javascript code won't be able to read / modify its content.

You can check the cookies tab in your browser and you will see whether it's readable or not.

In in your case though, django shouldn't be setting the flag as httpOnly as the docs describe how to read the value in javascript directly from the cookie.

A few things I can point out by experience:

  • The config object might not yet be filled with the data when you receive it within an interceptor. Therefore setting config.headers = ...; might trigger an error.

Make sure you write:

config.headers = config.headers || {}; 

before setting the headers so no 'config.headers is undefined' will be triggered.

  • Alternatively to directly reading the cookie, store the csrf value inside an hidden input as per default procedure.

You can do something like this (syntax might be incorrect):

<input type="hidden"
   name="csrftoken"
   value="{% csrf_token %}"/>
</div>

and then send the token within the interceptor with:

config.headers['x-csrftoken'] = document.querySelector('input[name="csrftoken"]').value;

In such case, since you do not need to read the cookie, it would be a huge plus to set it as httpOnly .

Axios has an order of precedence to config settings, so it could be possible that settings are overwritten by other code.

For example in Chrome browser, you can open the dev tools pane, click the Applications tab, and then on the left-side, you can click Cookies to view those to make sure the correct ones exist:

在此处输入图片说明

If you have an Axios request interceptor that defines the XSRF-TOKEN header, it would be overwritten by this:

axios.post(route('logout'), undefined, {
    headers: {
        'XSRF-TOKEN': 'bad',
    },
});

If you have a file, such as you would in many Laravel/Vue projects, called bootstrap.js or axios.js that declares global config settings, that setting could be overwritten by an interceptor.

For example:

// document head
<meta name="csrf-token" content="{{ csrf_token() }}">

...

// axios.js or bootstrap.js (imported in SPA app's main.js file)
window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

const token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    // an interceptor would overwrite this due to right-to-left precedence
    window.axios.defaults.headers.common['XSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

That last example there is very important because, that would be used for calling internal APIs. If you are calling an external API that utilizes CORS, such as Google, they can require specific headers and other headers can cause errors to be thrown.

To temporarily overwrite headers, you can use a pattern such as this where you are calling the external API:

// temporarily wipe 'XSRF-TOKEN' header for Google CORS
const instance = axios.create();

instance.defaults.headers.common = {};
instance.defaults.headers.common.accept = 'application/json';

const { data } = await instance.get('https://www.external.com/foobars');

That would overwrite an interceptor as well because instance by design takes precedence over global defaults.

Here is the request interceptor that I use:

import Cookies from 'js-cookie';

/**
 * Request interceptor: for each request to the server,
 * attach the CSRF token if it exists.
 *
 */
axios.interceptors.request.use(async (request) => {
    try {
        const csrf = Cookies.get('XSRF-TOKEN');
        request.withCredentials = true;

        if (csrf) {
            request.headers.common['XSRF-TOKEN'] = csrf;
        }

        return request;
    } catch (err) {
        throw new Error(`axios# Problem with request during pre-flight phase: ${err}.`);
    }
});

Since CSRF requires to be accessible by JavaScript, it must not be httpOnly , so rather than using a library such as js-cookie , you can get the cookie using document.cookie , but that returns a semicolon-delimited string of key/value pairs, so you could exercise your mind by making a function that extracts the CSRF.

console.log('cookies', document.cookie)

Bonus reading:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM