Django——CSRF_TOKEN跨站请求伪造 & session版登录认证

1.知识储备

1 django解决了csrf攻击,中间件: 
 django.middleware.csrf.CsrfViewMiddleware
'''
内部实现:
向浏览器发POST请求时,每次请求都会在模板里隐藏content ,会默认返回一个csrf  k:v 的值(k时csrf,v是随机字符串 可以在process_request里面取出,再根据k取出v进行校验),这个值会隐藏在页面中,
下次发请求时一定要带着这个隐藏的字符串,如果不想携带就报403 Forbidden禁止访问(黑客拿不到这个随机字符串,并且串有失效时间防止黑客破解拿出)
'''

2 后期中间件不能注释,每次发送post请求,都需要携带csrf_token随机字符串 -form表单提交 -在form表单中 {% csrf_token%}  '''
   {{csrf_token}}  #变量,不能用这个
  {% csrf_token %} #标签,使用这个
    '''
    -ajax提交(如何携带)
    方式一:放到data中 (***推荐)
     $.ajax({
            url: '/csrf_test/',
            method: 'post',
            data: {'name': $('[name="name"]').val(),
                'password': $('[name="password"]').val(),
                'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()
            },
            success: function (data) {
                console.log('成功了')
                console.log(data)

            },
            error: function (data) {
                console.log('xxxxx')
                console.log(data)

            }
        })
        方式二:放到data中
        'csrfmiddlewaretoken':'{{ csrf_token }}'
        方式三:放到头中
            headers:{'X-CSRFToken':'{{csrf_token}}'},
        
        
 # jquery.cookie.js
    -在浏览器中对cookie进行增,删,查,改
    -前后端分离(js操作cookie)
    
    
    
# 全局使用,局部禁csrf
    -在视图函数上加装饰器
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 全局启用,局部禁用(中间件不能注释,这个视图函数,已经没有csrf校验了)
 @csrf_exempt #加上这个装饰器
 def csrf_test(request):
     if request.method=='GET':
         return render(request,'csrf_test.html')
     else:
         name=request.POST.get('name')
         password=request.POST.get('password')
         print(name)
         print(password)
         return HttpResponse('登录成功')

# 全局禁用,局部使用csrf
@csrf_protect  #加上这个装饰器
def csrf_test(request):
    if request.method=='GET':
        return render(request,'csrf_test.html')
    else:
        name=request.POST.get('name')
        password=request.POST.get('password')
        print(name)
        print(password)
        return HttpResponse('登录成功')


# 古怪的使用方式,在urls.py中
path('csrf_test/', csrf_exempt(views.csrf_test))

2.模拟银行转账中出现的csrf攻击

settings.py

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

urls.py

from django.urls import path
from app01 import views
from django.views.decorators.csrf import csrf_exempt

urlpatterns = [
     
       path('', views.index),
       path('transfer/', views.transfer),
       path('csrf_test/', views.csrf_test),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

def login_auth(func):
    def inner(request, *args, **kwargs):
        # 登录校验
        name = request.session.get('name')
        if name:
            res = func(request, *args, **kwargs)
            return res
        else:
            path = request.get_full_path()
            return redirect('/login/?returnUrl=%s' % path)

    return inner

### session版登录
def login(request):
    if request.method == 'GET':

        return render(request, 'login.html')
    else:
        name = request.POST.get('name')
        password = request.POST.get('password')
        if name == 'lqz' and password == '123':
            # 写入session
            # 登录成功,重定向
            request.session['name']=name
            path = request.GET.get('returnUrl')
            if path:
                obj = redirect(path)
            else:
                obj = redirect('/index/')

            return obj
        else:
            return HttpResponse('用户名或密码错误')

@login_auth
def index(request):
    return render(request,'index.html')

@login_auth
def transfer(request):
    # /transfer/?from=lqz&to=egon&total=100
    f=request.GET.get('from')
    t=request.GET.get('to')
    total=request.GET.get('total')
    print('转账成功')
    return HttpResponse('转账成功')


def csrf_test(request):
    if request.method=='GET':
        return render(request,'csrf_test.html')
    else:
        name=request.POST.get('name')
        password=request.POST.get('password')
        print(name)
        print(password)
        return HttpResponse('登录成功')

csrf_test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1/jquery-3.3.1.min.js"></script>
    <title>Title</title>
</head>
<body>

{% csrf_token %}

<form action="" method="post">
 <p>用户名<input type="text" name="name"></p>
<p>密码<input type="password" name="password"></p>
<p><input type="submit" value="提交" id="submit"></p>
</form>
</body> </html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>银行正版网站</title>
</head>
<body>

<a href="/transfer/?from=lqz&to=egon&total=100">点我,给egon转100块钱</a>

</body>
</html>

 

posted @ 2020-10-23 12:32  1024bits  阅读(181)  评论(0编辑  收藏  举报