以下 response
标头未在浏览器中设置 cookie:
Access-Control-Allow-Origin: *
Allow: GET, HEAD, OPTIONS
Content-Length: 7
Content-Type: application/json
Date: Tue, 27 Apr 2021 15:58:02 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Set-Cookie: csrftoken=r5r2YcZZvJKs79cbLd24VSyNscpUsxJB6UuWiWO2TXriy6B4r8KDZrwSDyI091K1; expires=Tue, 26 Apr 2022 15:58:02 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Vary: Accept, Cookie, Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
我的 request
标题:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Host: 127.0.0.1:8000
Origin: http://localhost:3000
Pragma: no-cache
Referer: http://localhost:3000/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36
我是 Django 的新手,反应和“http 标头”相关的东西。
我的 Django 开发服务器运行在:
http://127.0.0.1:8000/
我的反应开发服务器运行在:
http://127.0.0.1:3000
/api/csrf/
来设置 csrf 令牌。# URL: /api/csrf/
class CSRFGet(APIView):
"""
Explicitly set csrf cookie
"""
@method_decorator(ensure_csrf_cookie)
def get(self, request):
return Response('hello')
当挂载 useProvideAuth
钩子时,我调用此端点。
function useProvideAuth() {
const [token, setToken] = useState(null);
const login = (username, password) => {
return axios.post(
'/auth/',
{
username: username,
password: password
})
.then(response => {
setToken(response.token)
})
}
useEffect(()=> {
axios.get(
'/csrf/'
)
},[])
return {
token,
login,
}
}
现在,当我向任何页面发出请求时,它会重定向到登录页面,我可以看到 api/csrf/
响应为:
Set-Cookie: csrftoken=LgHo2Y7R1BshM4iPisi5qCXhdHyAQK7hD0LxYwESZGcUh3dXwDu03lORdDq02pzG; expires=Tue, 26 Apr 2022 06:29:23 GMT; Max-Age=31449600; Path=/; SameSite=Lax
但是,cookie 根本没有设置。为什么会这样?
我获取 csrf cookie 的方法是否正确?如果我使用这种方法制造任何安全漏洞,请告诉我。
答案 0 :(得分:1)
您能否尝试将以下内容添加到 django-cors-headers
配置中并重试?
CORS_ALLOW_CREDENTIALS = 真
另外,请注意,如果您允许所有来源,上述配置可能不起作用。请参阅此 Mozilla 文档:Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’
如果你遇到这样的错误,我建议设置:
CORS_ALLOWED_ORIGINS = [
"http://127.0.0.1:3000",
]
或者更高级的东西:
CORS_ALLOWED_ORIGIN_REGEXES = [
r"^http://127.0.0.1:[0-9]{1,4}$",
]
最后,请确保您使用的是 django-cors-headers
版本 >= 3.5,因为当时上述 2 个配置具有不同的别名。
让我知道它是否有效,我很好奇。
答案 1 :(得分:1)
事实证明问题是,我使用 http://127.0.0.1:8000
进行 api 调用,而我的服务器在 http://localhost:8000
上。因此,我的 host
标头中的 origin
和 request
与同一个域不匹配。
Cookie 可以在同一个域下使用,与 different ports 和 subdomains 不同,但不能跨域使用。
就我而言,我猜 http://127.0.0.1:8000
和 http://localhost:8000
被认为是不同的域,因此浏览器没有设置我的 cookie。
感谢 Same-Origin
policy, 说明 Allow-Credentials
。我也试过了,但在我找到真正的原因之前仍然没有运气。