Ree*_*kle 40 django django-csrf reactjs redux axios
这是一个教育项目,不适用于生产.我不打算将用户登录作为其中的一部分.
我可以使用CSRF令牌对Django进行POST调用而无需用户登录吗?我可以不使用jQuery吗?我在这里超出了我的深度,肯定会混淆一些概念.
对于JavaScript方面,我发现了这个redux-csrf包.我不确定如何将它与我POST使用Axios的动作结合起来:
export const addJob = (title, hourly, tax) => {
console.log("Trying to addJob: ", title, hourly, tax)
return (dispatch) => {
dispatch(requestData("addJob"));
return axios({
method: 'post',
url: "/api/jobs",
data: {
"title": title,
"hourly_rate": hourly,
"tax_rate": tax
},
responseType: 'json'
})
.then((response) => {
dispatch(receiveData(response.data, "addJob"));
})
.catch((response) => {
dispatch(receiveError(response.data, "addJob"));
})
}
};
Run Code Online (Sandbox Code Playgroud)
在Django方面,我已经阅读了关于CSRF的这个文档,这通常与基于类的视图一起使用.
这是我到目前为止的观点:
class JobsHandler(View):
def get(self, request):
with open('./data/jobs.json', 'r') as f:
jobs = json.loads(f.read())
return HttpResponse(json.dumps(jobs))
def post(self, request):
with open('./data/jobs.json', 'r') as f:
jobs = json.loads(f.read())
new_job = request.to_dict()
id = new_job['title']
jobs[id] = new_job
with open('./data/jobs.json', 'w') as f:
f.write(json.dumps(jobs, indent=4, separators=(',', ': ')))
return HttpResponse(json.dumps(jobs[id]))
Run Code Online (Sandbox Code Playgroud)
我尝试使用csrf_exempt装饰器只是为了现在不必担心这个问题,但这似乎并不是这样的.
我已添加{% csrf_token %}到我的模板中.
这是我的getCookie方法(从Django docs中窃取):
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
Run Code Online (Sandbox Code Playgroud)
我已经读过我需要更改Axios CSRF信息:
var axios = require("axios");
var axiosDefaults = require("axios/lib/defaults");
axiosDefaults.xsrfCookieName = "csrftoken"
axiosDefaults.xsrfHeaderName = "X-CSRFToken"
Run Code Online (Sandbox Code Playgroud)
我在哪里粘贴实际的令牌,我从调用中获得的价值getCookie('csrftoken')?
Ree*_*kle 34
有三种方法.您可以在每个axios调用的标头中手动包含令牌,您可以xsrfHeaderName在每个调用中设置axios ,或者设置默认值xsrfHeaderName.
假设您已经将令牌的值存储在一个名为的变量中csrfToken.在axios调用中设置标题:
// ...
method: 'post',
url: '/api/data',
data: {...},
headers: {"X-CSRFToken": csrfToken},
// ...
Run Code Online (Sandbox Code Playgroud)
xsrfHeaderName通话中的设置:添加这个:
// ...
method: 'post',
url: '/api/data',
data: {...},
xsrfHeaderName: "X-CSRFToken",
// ...
Run Code Online (Sandbox Code Playgroud)
然后在您的settings.py文件中添加以下行:
CSRF_COOKIE_NAME = "XSRF-TOKEN"
Run Code Online (Sandbox Code Playgroud)
您可以为axios设置默认标头,而不是在每个调用中定义标头.
在您要导入axios以进行调用的文件中,在导入下方添加以下内容:
axios.defaults.xsrfHeaderName = "X-CSRFToken";
Run Code Online (Sandbox Code Playgroud)
然后在您的settings.py文件中添加以下行:
CSRF_COOKIE_NAME = "XSRF-TOKEN"
Run Code Online (Sandbox Code Playgroud)
编辑:显然它与Safari [2]略有不同
Edit2:您可能还需要设置[3]:
axios.defaults.withCredentials = true
Run Code Online (Sandbox Code Playgroud)
困惑:
...在每个XMLHttpRequest上,将自定义X-CSRFToken标头设置为CSRF标记的值.这通常更容易,因为许多JavaScript框架提供了允许在每个请求上设置标头的钩子.
作为第一步,您必须自己获取CSRF令牌.该令牌的推荐来源是csrftoken cookie,如果您已按照上述方式为视图启用了CSRF保护,则会设置该cookie.
注意
默认情况下,CSRF令牌cookie名为csrftoken,但您可以通过CSRF_COOKIE_NAME设置控制cookie名称.
默认情况下,CSRF标头名称为HTTP_X_CSRFTOKEN,但您可以使用CSRF_HEADER_NAME设置对其进行自定义.
这来自Axios文档.它表示您在此设置包含csrftoken标题的cookie 的名称和标题的名称:
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
Run Code Online (Sandbox Code Playgroud)
如我的问题所示,您可以访问cookie document.cookie.我唯一的cookie是我放在Django模板中的CSRF令牌.这是一个例子:
csrftoken=5knNceCUi9nL669hGGsvCi93XfqNhwTwM9Pev7bLYBOMXGbHVrjitlkKi44CtpFU
在那些令人困惑的文档中有一些概念被抛出:
csrftoken,它位于cookie中等号的左侧.yes*_*ema 15
我发现了,那axios.defaults.xsrfCookieName = "XCSRF-TOKEN";
和CSRF_COOKIE_NAME = "XCSRF-TOKEN"
在Mac OS上不适用于APPLE Safari
MAC Safari的解决方案很简单,只需更改XCSRF-TOKEN即可csrftoken
所以,在js-code中应该是:
import axios from 'axios';
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
Run Code Online (Sandbox Code Playgroud)
在settings.py中:
CSRF_COOKIE_NAME = "csrftoken"
Run Code Online (Sandbox Code Playgroud)
kre*_*ruz 10
这个配置对我来说没有问题Config axios CSRF django
import axios from 'axios'
/**
* Config global for axios/django
*/
axios.defaults.xsrfHeaderName = "X-CSRFToken"
axios.defaults.xsrfCookieName = 'csrftoken'
export default axiosRun Code Online (Sandbox Code Playgroud)
在花了太多时间研究并实施上述答案之后,我发现了这个问题的错误!我添加了这个答案作为已接受答案的补充。我已经按照提到的方式设置了所有内容,但对我来说,问题实际上在于浏览器本身!
如果在本地测试,请确保您通过127.0.0.1而不是localhost! localhost以不同的方式处理请求标头,并且不会在标头响应中显示 CSRF 令牌,但也会如此127.0.0.1!所以,而不是localhost:3000尝试127.0.0.1:3000!
希望这可以帮助。
小智 5
“简单的方法”几乎对我有用。这似乎有效:
import axios from 'axios';
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "XCSRF-TOKEN";
Run Code Online (Sandbox Code Playgroud)
在 settings.py 文件中:
CSRF_COOKIE_NAME = "XCSRF-TOKEN"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27557 次 |
| 最近记录: |