问题
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