django:跨域访问及CSRF防护

一,什么是跨域访问?

传统来看,django通过模板功能生成网页信息,网页的相关静态资源也是由django进行配置和读取的。如果静态资源的JavaScript文件使用Ajax请求API接口,那么当前请求就能从API中获得数据,这是因为当前发出请求的和所请求的API在同一个
这里需要提到“浏览器同源政策SOP(Same origin policy)”,这个所谓的“”,指的就是“协议+域名+端口号”,Netscape 公司最早引入同源政策是为了保证保证用户信息的安全,防止恶意的网站窃取数据,比如网页B就是不能读取网页A的cookie、网页B就是不能向非同源服务器发送Ajax请求等限制,减少XSS、CSFR等攻击。更多信息可以参考:浏览器同源政策及其规避方法
这里的“”和“”可以理解为一个意思。
从vue+django的前后端分离角度来说,在项目上线部署时,vue与django会部署在不同服务器,由于不满足“同源”或“同域”要求,那么vue向服务器发出的Ajax请求是到达不了django API接口的。显然这是不能满足数据获取任务的,所以跨域访问的需求就出现了。

二,django设置跨域访问

想要设置django的跨域访问,有许多方法,最好的是使用第三方功能应用django-cors-headers
还需要进行配置:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    '*'
)
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)
CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

三,CSRF

1,什么是CSRF?

跨站请求伪造CSRF是一种网络攻击,它迫使最终用户在当前已通过身份验证的Web应用程序上执行不需要的操作。 例如通过电子邮件或聊天发送链接,攻击者可能会诱骗Web应用程序的用户执行攻击者选择的操作。 如果受害者是普通用户,则成功的CSRF攻击会迫使用户执行状态更改请求,例如转移资金,更改其电子邮件地址等。 如果受害者是管理帐户,CSRF可能会破坏整个Web应用程序。

2,一个CSRF例子

可以通过多种方式欺骗最终用户从Web应用程序加载信息或向Web应用程序提交信息。 为了执行攻击,我们必须首先了解如何为受害者执行有效的恶意请求。 让我们考虑以下示例:爱丽丝希望使用容易受到CSRF攻击的bank.com Web应用程序向鲍勃转账100美元。 攻击者玛丽亚想要诱使爱丽丝将钱寄给玛丽亚。 攻击将包括以下步骤:

  1. 建立漏洞利用URL或脚本
  2. 诱使爱丽丝执行行动

1,GET方法:
如果将应用程序设计为主要使用GET请求来传输参数并执行操作,则汇款操作可能会简化为以下请求:

GET http://bank.com/transfer.do?acct=BOB&amount=100HTTP/1.1

Maria使用原始URL并用她自己替换了收款人名称,同时提高了转账金额:

http://bank.com/transfer.do?acct=MARIA&amount=100000

接下来,Maria需要在Alice登录到银行应用程序时诱使Alice加载此URL。 通常使用以下技术之一完成此操作:

  1. 发送带有HTML内容的未经请求的电子邮件
  2. 在受害者进行在线银行业务时可能会访问的页面上植入漏洞利用这个URL或脚本

总之,漏洞URL可以伪装成普通链接,鼓励受害者单击它:

<img src="http://bank.com/transfer.do?acct=MARIA&amount=100000" width="0" height="0" border="0">

如果该图像标签包含在电子邮件中,爱丽丝将看不到任何东西。 但是,浏览器仍将请求提交给bank.com,而没有任何视觉上的迹象表明转移已经发生。
使用GET对应用程序进行CSRF攻击的真实例子是2008年的uTorrent漏洞,该漏洞已被大规模用于下载恶意软件。

2,POST方法:
GET和POST攻击之间的唯一区别是受害者执行攻击的方式。让我们假设银行现在使用POST:

POST http://bank.com/transfer.do HTTP/1.1
acct=BOB&amount=100

此类请求不能使用标准A或IMG标签来传递,但可以使用FORM标签来传递:

<form action="http://bank.com/transfer.do" method="POST">

<input type="hidden" name="acct" value="MARIA"/>
<input type="hidden" name="amount" value="100000"/>
<input type="submit" value="View my pictures"/>

</form>

此表单将要求用户单击“提交”按钮,但这也可以使用JavaScript自动执行:

<body onload="document.forms[0].submit()">

<form...

3,Other HTTP methods:
现代web应用程序api经常使用其他HTTP方法,比如PUT或DELETE。让我们假设脆弱的银行使用了以JSON块作为参数的PUT:

`PUT http://bank.com/transfer.do HTTP/1.1`

`{
     
      "acct":"BOB", "amount":100 }`

也可以使用嵌入漏洞利用页面的JavaScript来执行此类请求:

<script>
function put() {
    
    
    var x = new XMLHttpRequest();
    x.open("PUT","http://bank.com/transfer.do",true);
    x.setRequestHeader("Content-Type", "application/json");
    x.send(JSON.stringify({
    
    "acct":"BOB", "amount":100})); 
}
</script>

<body onload="put()">

当然,攻击方式不止使用HTTP发送请求,还可以通过劫持cookie的方式获取信息。
幸运的是,由于同源策略的限制,这个请求将不会被现代web浏览器执行。这个限制在默认情况下是启用的,除非目标网站使用CORS明确地打开来自攻击者(或所有人)来源的跨源请求,其头文件为:Access-Control-Allow-Origin:

四,django的CSRF防护

这样看来,跨域访问与CSRF防护似乎是矛盾的关系,但是django有简单但有效的防护机制。
例如在进行表单提交时,django会自动在发布表单中添加隐藏的表单字段csrfmiddlewaretoken ,并通过与后台的csrfmiddlewaretoken 进行匹配来检查请求的正确值,增加对跨站点请求伪造的保护。
使用方法两步走:

  1. 配置 'django.middleware.csrf.CsrfViewMiddleware'
  2. 在使用POST方法的表单所在处使用{% csrf_token %}
  3. 使用RequestContext上下文来渲染响应(这是默认的)

情况一:对表单设置CSRF防护

templates/index.html:
<html>
<body>
<form action="" method="post">
    {
    
    % csrf_token %}
    <div>用户名:</div>
    <input type="text" name='username'>
    <div>密 码:</div>
    <input type="password" name='password'>
    <div><button type="submit">确定</button></div>
</form>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
如果要取消表单的CSRF防护,需要先在模板中删除{% csrf_token %},再在视图函数前添加@csrf_exempt,否则会出现403异常。

情况二:对视图函数设置CSRF防护

在视图函数前添加@csrf_exempt。

index/views.py:
# 取消CSRF防护
@csrf_exempt
def index(request):
    return render(request, 'index.html')

情况三:Ajax请求的CSRF防护

var csrf = $('input[name="csrfmiddlewaretoken"]'.val());
或
$.ajaxSetup({
    
     data: {
    
    csrfmiddlewaretoken: ‘{
    
    {
    
     csrf_token }}}, });
$.post


获得:
<QueryDict: {
    
    'csrfmiddlewaretoken': ['h9mYGUqy9Xr2jIPUebtb4qyNfyVNbi5GDD6kSVuH97VJgyzYJ8sGkyiFQ3xo3Nx7'], 'username': ['root'], 'password': ['root']}>
[17/Sep/2020 17:23:41] "POST / HTTP/1.1" 200 898

猜你喜欢

转载自blog.csdn.net/dangfulin/article/details/108625628