第六十四天 csrf, auth,中间件插拔解释

tuq2791 / 2024-02-05 / 原文

一、csrf跨站请求伪造

1.简介
	钓鱼网站:假设是一个跟银行一模一样的网址页面 用户在该页面上转账
	账户的钱会减少 但是受益人却不是自己想要转账的那个人

2.模拟
一台计算机上两个服务端不同端口启动 钓鱼网站提交地址改为正规网站的地址
def transfer(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        target_user = request.POST.get('target_user')
        money = request.POST.get('money')
        print(f'{username}给{target_user}转了{money}')
    return render(request, 'transfer.html')
原来的真实的网站——————————————————————————————————————————————————————————————————————————
<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>
    <input type="submit">
</form>
伪造的钓鱼网站———————————————————————————————————————————————————————————————————————————
<form action="127.0.0.1:8080/transfer/" method="post">
    <p>username:
        <input type="text" name="username">
    </p>
    <p>target_user:
        <input type="text">
        <input type="text" name="target_user" value="中东悍匪" style="display: none">
    </p>
    <p>money:
        <input type="text" name="money">
    </p>
    <input type="submit">
</form>
"""
钓鱼网站的post的地址和真实网站的一样
钓鱼网站把已经设定好的值通过style="display: none"隐藏起来,并且给影藏name不给用户输入的东西name
"""

3.预防
	csrf策略:通过在返回的页面上添加独一无二的标识信息从而区分正规网站和钓鱼网站的请求
	csrf在服务端是通过settings的中间件创建的
	MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
]

二、csrf操作(403 Forbidden)

MIDDLEWARE = ['django.middleware.csrf.CsrfViewMiddleware',]

一.form表单
	<form action="" method="post">
    	{% csrf_token %}
	</form>
"""
1.查看网页源代码你会发现 {% csrf_token %} 自动变成了 <input type="hidden" name="csrfmiddlewaretoken" value="fVb50OZQMO5bYRPrV35r8rgbMJfHZ5X5LIstpbTHsmPu7z933FC3dVb6TVugwLTv">  并且每次访问后都会变化
"""


二.ajax
方式1:先编写csrf模板语法 然后利用标签查找和值获取 手动添加
<h1>这是真正的网站</h1>
{% csrf_token %}
<button id="d1">点我发送ajax请求</button>
<script src="/static/csrf.js"></script>
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
            success:function (args){
            }
        })
    })
"""
1.利用ajax在传数据的同时把csrf的数据同时传输过去
2.csrfmiddlewaretoken是在前端的源代码里面找到的,不用去记忆
"""

方式2:直接利用模板语法即可
<button id="d1">快点我,点我呀</button>
{% csrf_token %}
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':'jojo', 'csrfmiddlewaretoken':'{{ csrf_token }}'}
        })
    })
</script>
"""
1.'{{ csrf_token }}'可以替代上面的内容,注意要加双引号
"""

方式3:通用方式(js脚本)
# 创建static文件夹,在文件夹下面创建文件csrf.js
<button id="d1">快点我,点我呀</button>
<script src="/static/csrf.js"></script>
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':'jojo'}
        })
    })
</script>

# 具体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);
    }
  }
});