csrf跨站请求伪造,csrf校验策略,相关装饰器

csrf跨站请求伪造

钓鱼网站:

模仿一个正规的网站,让用户在该网站上做操作,但是操作的结果会影响到用户正常的网站账户,其中有一些猫腻。
  eg:英语四六级考试需要网上先缴费,但是你会发现卡里的钱扣了但是却交到了一个莫名其妙的账户,并不是真正的四六级官方账户。

真假网站的代码区别:

urls.py

from app01 import views


urlpatterns = [
    path('admin/', admin.site.urls),
    # 转账接口
    path('transfer/',views.transfer_func),
]

viwes.py

from django.shortcuts import render

def transfer_func(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        target_name = request.POST.get('target_name')
        money = request.POST.get('money')
        print(f"{username}给{target_name}转了{money}元")
    return render(request,'transferPage.html')

 效果展示

 当我们输入同样的用户信息,提交之后得到的结果却是不一样的

 打印结果

真网站: 

 

假网站:

 

 

 思考:如何区分真假网站页面发送的请求

csrf校验策略

CSRF是什么?

CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

CSRF可以做什么?

你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。

在提交数据的位置添加唯一标识 。

我们之前在发送POST请求时是将settings.py中的这条中间件注掉的,当我们把它打开之后,是无法直接发送POST请求的,添加唯一标识之后就可以正常发送了。

1.form表单操作csrf策略

form表单内部添加 {% csrf_token %}

2.ajax请求csrf策略

方式1: 通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

自己动手取值,较为繁琐,不推荐使用

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  data: {
    "username": "Tonny",
    "password": 123456,
    "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中
  },
  success: function (data) {
    console.log(data);
  }
})

 

方式2: 通过获取返回的cookie中的字符串,放置在请求头中发送。

注意:需要引入一个jquery.cookie.js插件。

利用模板语法自动获取(一定要用引号引起来)

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  headers: {"X-CSRFToken": $.cookie('csrftoken')},  // 从Cookie取csrf_token,并设置ajax请求头
  data: {"username": "Q1mi", "password": 123456},
  success: function (data) {
    console.log(data);
  }
})

 

方式3:直接引入一个js脚本即可(官网提供的)

参考:https://www.cnblogs.com/Dominic-Ji/p/9234099.html

# 直接使用JS脚本 拓展性最高

<script src="/static/csrf.js"></script>
这里我们把下方代码写到一个js文件中然后使用的时候在网页中导入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);
        }
    }
});

将上面的文件配置到你的Django项目的静态文件中,在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)。

更多细节详见:Djagno官方文档中关于CSRF的内容

csrf相关装饰器

当我们知道csrf的作用和使用方式后,我们联系实际情况考虑到实际应用中会出现下列情况:

  • 整个django项目都校验csrf,但是某些个视图函数\类不想校验
  • 整个django项目都不校验csrf ,但是某些个视图函数\类需要校验

根据FBV和CBV的分类,导入时候有所区别:

FBV添加装饰器的方式(与正常函数添加装饰器一致)

from django.views.decorators.csrf import csrf_exempt, csrf_protect

# @csrf_exempt
想让csrf校验检测就使用装饰器@csrf_protect,不想让csrf校验检测就使用@csrf_exempt
@csrf_protect
def transfer_func(request):pass

CBV添加装饰器的方式(与正常情况不一样,需要注意)

主要有三种方式

# @method_decorator(csrf_protect, name='post')  # 方式2:写在类的上方,单独生效,给类里面的post方法添加装饰器
class MyView(views.View):

    '''这里需要会去看CBV的源码剖析,CBV源码内起作用的也是dispaly,通过反射执行字符串表示的功能,因此第三种方式是整个类中生效的。'''
    @method_decorator(csrf_protect)  # 方式3:整个类中生效    
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    @method_decorator(csrf_protect)  # 方式1:写在某一个方法的上方,只对此方法生效
    def post(self, request):
        return HttpResponse('from cbv post view')
  
# 注意有一个装饰器是特例只能有一种添加方式>>>:csrf_exempt
     只有在dispatch方法处添加才会生效

 

posted @ 2023-01-13 17:04  莫~慌  阅读(52)  评论(0编辑  收藏  举报