Django中间件之csrf跨站请求伪造

csrf跨站请求伪造

CSRF(Cross Site Request Forgery) 跨站请求伪造。也被称为One Click Attack和Session Riding,通常缩写为CSRF或XSRF。如果从名字你还不不知道它表示什么,你可以这样理解:攻击者(黑客,钓鱼网站)盗用了你的身份,以你的名义发送恶意请求,这些请求包括发送邮件、发送消息、盗取账号、购买商品、银行转账,从而使你的个人隐私泄露和财产损失。

CSRF攻击实例

听了这么多,可能大家还云里雾里,光听概念可能大家对于CSRF还是不够了解,下面我将举一个例子来让大家对CSRF有一个更深层次的理解。

# 以钓鱼网站为例:
	我搭建一个跟正规网站一模一样的界面(中国银行)
	用户不小心进入到了我们的网站,用户给某个人打钱
	打钱的操作确确实实是提交给了中国银行的系统,用户的钱也确确实实减少了
	但是唯一不同的时候打钱的账户不是用户想要打的账户变成了一个莫名其妙的匿名账户
# 内部本质
	我们在钓鱼网站的页面 针对对方账户 只给用户提供一个没有name属性的普通input框
	然后我们在内部隐藏一个已经写好name和value的input框
    那么我们在提交的时候只向后端提交存在name属性和value值得input框内容
    此时隐藏得input框得name和value属性值是固定得,相当于'诈骗'账户

示例:

8000端口:html

<h1>我是正真得网站</h1>
<form action="" method="post">
    <p>username: <input type="text" name="username"></p>
    <p>target_user: <input type="text" name="target_user"></p>
    <p>money: <input type="text" name="money"></p>
    <p><input type="submit"></p>

</form>

8001端口:html

<h1>我是钓鱼网站</h1>
<form action="http://127.0.0.1:8000/transfer/" method="post">
    <p>username: <input type="text" name="username"></p>
    <p>target_user: <input type="text"></p>
    <input type="text" name="target_user" value="gary" style="display: none">
    <p>money: <input type="text" name="money"></p>
    <p><input type="submit"></p>
</form>

需要将钓鱼网站的端口号修改,不然冲突
display:none可以隐藏某个元素,且隐藏的元素不会占用任何空间。也就是说,该元素不但被隐藏了,而且该元素原本占用的空间也会从页面布局中消失。

如何避免上述问题呢:

# csrf跨站请求伪造校验
		网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
		当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden)如果成功则正常执行

form如何符合校验

前提:

'django.middleware.csrf.CsrfViewMiddleware',  # 需要去配置文件将csrf中间件打开
# 只需要在form表单内添加:{% csrf_token %}

<h1>我是正真得网站</h1>
<form action="" method="post">
    {% csrf_token %}
    <p>username: <input type="text" name="username"></p>
    <p>target_user: <input type="text" name="target_user"></p>
    <p>money: <input type="text" name="money"></p>
    <p><input type="submit"></p>
</form>

ajax如何符合校验

# 除了form表单可以提交post请求之外,ajax也是可以提交post请求的
# 那么上述方法只是针对form表单的,那么我们接下来来研究ajax是如何

方式一:

// 第一种 利用标签查找获取页面上的随机字符串
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'username':$('[name=username]').val(),'target_user':$('[name=target_user]').val(),'money':$('[name=money]').val(),'csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},
            // 主动取出csrfmiddlewaretoken对应的值发送给后端
            success:function (){

            }
        })
    })
</script>

方式二:

# 利用模版语法提供的快捷书写 (如果是前后端分离的项目,就不方便使用该方法)
    
data:{'username':$('[name=username]').val(),'target_user':$('[name=target_user]').val(),'money':$('[name=money]').val(),'csrfmiddlewaretoken':{{ csrf_token }},

方式三:

// 第三种 通用方式直接拷贝js代码并应用到自己的html页面上即可 
{% load static  %}
<script src="{% static 'js/mycsrf.js' %}"></script>
 
 
data:{'username':$('[name=username]').val(),'target_user':$('[name=target_user]').val(),'money':$('[name=money]').val()},

配置文件:

// 需手动创建js文件

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 = jQuery.trim(cookies[i]);
            // 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;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

csrf相关装饰器

需求:
	1.网站整体都不校验csrf,就单单几个视图函数校验
    2.网站整体都校验csrf,就单单几个不视图函数不校验
# 这里django给我们提供了现成的两个装饰器供我们使用
1. csrf_protect   需要校验
2. csrf_exempt   忽视校验

csrf_exempt忽视校验:

csrf_protect需要校验

研究CBV添加装饰器是否可行:

from django.views import View

# @method_decorator(csrf_protect,name='post')  # 针对csrf_protect 第二种方式可以
# @method_decorator(csrf_exempt,name='post')  # 针对csrf_exempt 第二种方式不可以
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
    # @method_decorator(csrf_protect)  # 针对csrf_protect 第三种方式可以
    # @method_decorator(csrf_exempt)  # 针对csrf_exempt 第三种方式可以
    def dispatch(self, request, *args, **kwargs):
        return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return HttpResponse('get')

    # @method_decorator(csrf_protect)  # 针对csrf_protect 第一种方式可以
    # @method_decorator(csrf_exempt)  # 针对csrf_exempt 第一种方式不可以
    def post(self,request):
        return HttpResponse('post')

总结:

针对csrf_protect:需要校验
	三种方式都可行。
针对csrf_exempt:忽视校验
	只有给dispatch方法添加才可行
    (可以在dispatch方法紧上方添加装饰器,
     也可以使用@method_decorator(csrf_exempt,name='dispatch')在类上方添加装饰器)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值