Django基础(12)_csrf跨站请求伪造

 

什么是CSRF   

 详述CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。攻击者通过HTTP请求江数据传送到服务器,从而盗取回话的cookie。盗取回话cookie之后,攻击者不仅可以获取用户的信息,还可以修改该cookie关联的账户信息。

 

服务器验证token的原理

token字符串的前32位是salt(盐), 后面是加密后的token, 通过salt能解密出唯一的secret。
django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法。

表单中的csrfmiddletoken, cookie中的csrftoken

  

1 在响应的页面中加入{% csrf_token %}标签,那么在进行模板渲染是会生成如下标签
    <input type="hidden" name="csrfmiddlewaretoken" value="ppwN8yg1wVEyXDxtMpVIrc4zV3gHiDKKb9rwGPLaSGRc0HKhXAwpNrKjGDUHIxjj">

2 并且在响应还有这个    {% csrf_token %}标签的页面时,会添加cookie键值对,如下
    csrftoken:lsMQeJgVbIKKxlfz6umgYM8WOWx1Njr77cHzM0L4xtXoApsnhFXXk1OGzwb1dd0G    

3 当用户从该页面提交数据时,会携带csrfmiddlewaretoken:ppwN8yg1wVEyXDxtMpVIrc4zV3gHiDKKb9rwGPLaSGRc0HKhXAwpNrKjGDUHIxjj和cookie键值对

4 取出cookie中的csrftoken值和请求数据部分的csrfmiddlewaretoken的值,两者进行比较,这个随机字符串叫做token字符串. django如果在请求数据部分找不到tokne值,会去请求数据中的请求行部分,找一个叫做X-CSRFToken的键值对,如果这个键对应的值和cookie中csrftoken对应的值相同,也能通过认证.
    过程:
        token字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret字符串。
        secret:是settings配置文件中的serect_key:
              SECRET_KEY = 's!xbzez1zxrevmq7k_89%%-z&#)e7686pyq8pg@_bp_k_2s^ho'
        django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法。
        如果不同就403 forbidden

 

form表单中的token  


服务器给表单中返回一个csrfmiddlewaretoken

 

 

cookie中的token 

当用户提交get请求, 服务器就会给浏览器的cookie中返回一个csrftoken

 

form表单设置token

<!--form表单中验证token-->
<h1>天上人间会员登录页面</h1>
<form action="" method="post" >
    {% csrf_token %}
    <div>{{ error }}</div>
    用户名: <input type="text" name="username"  value="{{ username }}">
    密码: <input type="password" name="password" value="{{ password }}">
    <input type="submit">
</form>

 

ajax通过django的csrf_token验证

首先我们先看一下不给ajax请求设置csrf_token的情况

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>fivenian</title>

</head>
<body>


<!--form表单中验证token-->
{#<h1>天上人间会员登录页面</h1>#}
{#<form action="" method="post" >#}
{#    {% csrf_token %}#}
{#    <div>{{ error }}</div>#}
{#    用户名: <input type="text" name="username"  value="{{ username }}">#}
{#    密码: <input type="password" name="password" value="{{ password }}">#}
{#    <input type="submit">#}
{#</form>#}

<!--ajax验证token-->
<h1>ajax的token认证</h1>
用户名: <input type="text" name="username" id="id_username">
<br>
密码: &nbsp; <input type="password" name="password" id="id_password">
<br>
<button id="btn">登录</button>
<h3 id="error_msg"></h3>   <!--若请求失败打印一下错误信息-->
<h3 id="success_msg"></h3>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
    $('#btn').click(function (){

        var username = $('#id_username').val();
        var password = $('#id_password').val();
        $.ajax({
            url:'/login/',
            type:'post',
            data:{'uname':username,'pwd':password},
            success:function (res){
                $('#success_msg').text('请求成功')
            },
            error(error){
                console.log(error)
                $('#error_msg').text(error.responseText)
            }
        })
    })
</script>
</html>
View Code

 

ajax请求中添加csrf_token的三种方式

方法一: 在我们的body代码中添加上 {% csrf_token %} , 然后获取token添加在data中发送到服务器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>fivenian</title>

</head>
<body>


<!--ajax验证token-->
<h1>ajax的token认证</h1>
  {% csrf_token %}    <!--在body中添加上-->
用户名: <input type="text" name="username" id="id_username">
<br>
密码: &nbsp; <input type="password" name="password" id="id_password">
<br>
<button id="btn">登录</button>
<h3 id="error_msg"></h3>   <!--若请求失败打印一下错误信息-->
<h3 id="success_msg"></h3>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>

    $('#btn').click(function (){
        var username = $('#id_username').val();
        var password = $('#id_password').val();
        var token = $("[name='csrfmiddlewaretoken']").val()   // 获取token 然后加到data中
        $.ajax({
            url:'/login/',
            type:'post',
            data:{uname:username,pwd:password,csrfmiddlewaretoken:token},
            success:function (res){
                $('#success_msg').text('请求成功')
            },
            error(error){
                console.log(error)
                $('#error_msg').text(error.responseText)
            }
        })
    })
</script>
</html>

 

# views.py
def
login(request): if request.method == 'POST': print(request.POST) rep = HttpResponse('not ok') rep.status_code = 400 return rep return render(request, 'home/login.html')

 

然后在提交一下我们的form表单,可以看到访问成功,我们返回的错误也打印了出来

 

 

 

 

 

方法二:  直接在data中将token对应的随机字符串发送过去, 

    csrfmiddlewaretoken:'{{ csrf_token }}'

 


提交表单可以看到 变成了随时字符串
    $('#btn').click(function (){
        var username = $('#id_username').val();
        var password = $('#id_password').val();
        // var token = $("[name='csrfmiddlewaretoken']").val()
        $.ajax({
            url:'/login/',
            type:'post',
            data:{uname:username,pwd:password,csrfmiddlewaretoken:'{{ csrf_token }}'}, // 这里的{{ csrf_token }} 拿到的就是 {% csrf_token %}生成的input标签中的value属性对应的token值
            success:function (res){
                $('#success_msg').text('请求成功')
            },
            error(error){
                console.log(error)
                $('#error_msg').text(error.responseText)
            }
        })
    })

 

 

方法三: 添加请求头键值对, 键必须叫做 X-CSRFToken , 值就是cookie中的token值

jquery操作cookie,下载jquery.cookie.js文件

# 我们需要使用jquery操作cookie,所以先下载文件

http://plugins.jquery.com/cookie/
https://www.bootcdn.cn/jquery-cookie/

 

    注意:

      如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。

      如果你的视图渲`染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。

      这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。

django.views.decorators.csrf import ensure_csrf_cookie


@ensure_csrf_cookie
def login(request):
    pass

 


<
script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script> $('#btn').click(function (){ var username = $('#id_username').val(); var password = $('#id_password').val(); // var token = $("[name='csrfmiddlewaretoken']").val() $.ajax({ type:'post', url:'/login/', data:{uname:username,pwd:password}, headers:{ // 设置响应头键值对 'X-CSRFToken': $.cookie('csrftoken'), }, success:function (res){ $('#success_msg').text('请求成功') }, error(error){ console.log(error) $('#error_msg').text(error.responseText) } }) }) </script>

 

既然使用了 jquery.cookie.js  我们就介绍下使用jquery操作cookie

 

添加cookie
    $.cookie('the_cookie', 'the_value');
读取cookie
    $.cookie('the_cookie');  #the_cookie是键
删除cookie
    $.cookie('the_cookie', null);   //通过传递null作为cookie的值即可

 

 

 

------------恢复内容结束------------

posted @ 2020-12-03 17:33  死里学  阅读(96)  评论(0)    收藏  举报