How to use Django's CSRF protection in axios for different host?

◇◆丶佛笑我妖孽 提交于 2021-01-29 04:54:11

问题


I am working on ReactJS project as frontend and Django as backend and having trouble with CSRF protection!

I am using Django CORS headers and I have done all set up correctly. It works as long as I have localhost to access both front and back ends. My frontend is running on localhost:3006 and backend us running on localhost:8899 port. So frontend is setting csrftoken cookie and sending it with post request.

I am using axios.create() with withCredentials = true and it works fine. Now when my co-worker is running same frontend code from his system, trying to connect to backend that is running on my machine, he is getting 403 csrf cookie not found! At this time, he is running his frontend on localhost:3006, his own localhost and connecting to backend of my-ip:8899. So I believe that we would have this problem too on production when we will have www.example.com serving frontend and api.example.com serving backend as cookies of frontend host wont get sent to api host!

My cors header settings in django,

# Origin white list
CORS_ORIGIN_WHITELIST = [
    'http://localhost',
    'http://127.0.0.1',
    'http://192.168.1.165',
    'http://192.168.1.165:3006',
]

CORS_EXPOSE_HEADERS = (
    'Access-Control-Allow-Origin: *',
)

# Allowed methods
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
)

# Allowed headers
CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'X-tz',
    'x-tz',
    'x-requested-with',
)

# # CSRF COOKIE NAME
CSRF_COOKIE_NAME = "csrftoken"

# To allow default credentials
CORS_ALLOW_CREDENTIALS = True

CORS_ORIGIN_ALLOW_ALL = True

and my Axios create code is,

let tz = "UTC";

try {
    tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
    consoleError(e);
}

const API = axios.create({
    baseURL: process.env.REACT_APP_API_HOST,
    timeout: 30000,
    withCredentials: true,
    xsrfCookieName: CSRF_COOKIE_NAME,
    xsrfHeaderName: "X-CSRFToken",
    headers: {'X-tz': tz}
});

So as I said, if I am connecting from my machine to my machine using localhost/IP and ports, it works but when my co-worker is trying to connect from his localhost/IP frontend to my ip-backend it doesn't allow him to make POST request without CSRF cookie! I don't want to bypass Django security of CSRF with decorator. So can anyone tell me what am I doing wrong here?


回答1:


CSRF works by matching the token in the cookie to the token in the X-CSRFToken header (or in the form data). Your axios request must sent both.

It's sending the token in the X-CSRFToken. But it's not sending the cookie to api.yourhost.com because the cookie was set for the domain www.yourhost.com. That's the default in Django.

Change CSRF_COOKIE_DOMAIN to your eTLD+1 domain preceded by a ., i.e. .yourhost.com, so that it's sent to every of your subdomains, including api.yourhost.com.

Now in your test scenario, this cannot work, because the cookie set by your coworker's frontend is for localhost whereas the axios request is to your ip. There's no solution for this except have your co-worker get the frontend also from your ip.



来源:https://stackoverflow.com/questions/57714625/how-to-use-djangos-csrf-protection-in-axios-for-different-host

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!