关于前后端分离时,如何解决djaogo的CSRF问题

先说一句,这里我还没有找到我觉得合理的解决方案,记录了一些概念性的东西,还有别人的一些解决方法,但是我总觉得有点问题,希望有路过的同学,如果看明白了我的疑惑,能帮我解惑一下

1.如果前后端都使用django来完成,那么这个CSRF防御应该是挺好解决的,可以在表单中加入{% csrf_token %}来完成。

<form action="add_book" method="post">
        {% csrf_token %}
        name: <input name="bookname">
        <button type="submit">提交</button>
    </form>

这样,当浏览器在渲染这个表单时,会随机生成一个隐藏的input,value为随机的字符串,同时将一个csrftoken 存到cookie中

<input type="hidden" name="csrfmiddlewaretoken" value="3LO2cifZp9TcZR1CHYDzmQL2DzMcrEAC7VWOUpiE3wF3Fu3aEwR6k9YiiBXE5RbS">

==================================

csrftoken: fAbDG5qO1xRaEQGPvbOnFmhYInTCBToljKjpocttFUD1ktInsJ2UDFuenp44f6ZB

提交表单时,django 会将这两个进行验证,从而完成防御。
在这里,csrftoken的生成和存储都是直接在django完成,外域无法获取cookie中的csrftoken,因此无法进行请求伪造。
2. 那么前后端分离时怎么办呢?比如vue + django(这是我的疑惑所在)
在vue中显然无法通过{% csrf_token %}来生成随机字符串和csrftoken。这是可以通过在表单提交时,将cookie 中的csrftoken作为请求头进行发送就可以了,而且不需要再携带随机字符串。

header:
X-CSRFToken: tCbZrFYaUFkF6tqRPIRMQr4Brh3g1VzW5qLXSJhoLrswjzjre2gF4OzYqtNFkpQo

如果cookie中还没有csrftoken,我们可以通过访问一个指定函数让django显式生成,并存储到cookie中。

from django.middleware.csrf import get_token
def get_token(request):
   if request.method == "GET":
		token = django.middleware.csrf.get_token(request)
		return HttpResponse("OK")

这样就可以从cookie中获取csrftoken,并将其放置在请求头中。
以上是我在百度上找到的前后端分离解决方法,绝大部分的解决思路都是一致的。但是这样怎么可以进行防御呢,下面写出我的一些疑惑:
首先我同样可以在另外一个网站通过js来发送一个Get请求,虽然有同源策略,但是还是有办法可以完成的。这样这个cookie就会保存在我当前网站下,那么我就可以去获取,并且设置在请求头中,然后进行请求伪造,我利用vue确实也实现了这个。那这样CSRF检测不就失效了吗? 那么原则上,可以使用这种方法来对所有使用django的网络来发动CSRF攻击,不知道我哪里理解出了问题,希望看到这篇博客的同学给我解惑一下!!!

### Django 前后端分离CSRF 处理 在现代Web开发中,前后端分离架构变得越来越普遍。对于基于Django框架的应用程序,在这种架构下保持CSRF防护的有效性和安全性至关重要。 #### 获取并设置CSRF Token 为了使前端能够安全地发起POST请求到Django服务器,必须先从服务器获取CSRF令牌,并将其作为自定义HTTP头的一部分发送给服务器[^1]。这可以通过创建专门用于返回CSRF令牌的API接口来完成: ```python from django.middleware.csrf import get_token from django.http import JsonResponse def get_csrf_token(request): token = get_token(request) return JsonResponse({'csrfToken': token}) ``` 此视图允许客户端通过访问特定URL(例如`/get_token/`)获得当前会话对应的CSRF令牌。 #### 客户端配置 一旦获得了CSRF令牌,就需要确保每次向受保护资源发出非GET类型的AJAX请求之前都将该令牌附加到请求头部。以下是使用JavaScript Fetch API的一个简单例子: ```javascript // JavaScript (Frontend) async function fetchWithCsrf(url, method='POST', body=null){ const response = await fetch('/api2/get_token'); let { csrfToken } = await response.json(); const headers = new Headers({ 'X-CSRFToken': csrfToken, 'Content-Type': 'application/json' }); const options = { method: method.toUpperCase(), credentials: 'include', headers: headers, ...(body && {'body': JSON.stringify(body)}) }; return fetch(url, options); } ``` 这段代码展示了如何构建一个通用函数`fetchWithCsrf()`,它接受目标URL和其他可选参数如HTTP动词和负载数据。重要的是要注意这里的`credentials: 'include'`选项,这是为了让浏览器随同跨域请求一起发送Cookie所必需的[^4]。 #### 后端路由配置 最后一步是更新Django应用中的URL模式以包含上述新添加的功能。假设已经有一个名为`app/views.py`文件,则可以在项目的根级urls.py中加入相应的路径映射[^2]: ```python urlpatterns = [ ... path('api2/get_token', getToken), ... ] ``` 这里假定`getToken`就是上面提到的那个用来分发CSRF令牌的方法名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值