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

Django中间件

中间件介绍和常用内置中间件(简介)

0 中间件:数据库中间件(mycat,分库分表),服务器中间件(tomcat,nginx,消息队列中间件(rabbitmq)
1 django中间件(Middleware):介于request与response处理之间的一道处理过程,在全局上改变django的输入与输出

django内置中间件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware', # 安全中间件
    'django.contrib.sessions.middleware.SessionMiddleware', # 会话中间件:处理session
    'django.middleware.common.CommonMiddleware',  # 站点中间件:处理是否带斜杠的
    'django.middleware.csrf.CsrfViewMiddleware',  # CSRF保护中间件:跨站请求伪造的处理
    'django.contrib.auth.middleware.AuthenticationMiddleware', # 认证中间件:提供用户认证服务
    'django.contrib.messages.middleware.MessageMiddleware',# 消息中间件:基于cookie或者会话的消息功能
    'django.middleware.clickjacking.XFrameOptionsMiddleware', # X-Frame-Options中间件:点击劫持保护
]

# SessionMiddleware源码
django.contrib.sessions.middleware.SessionMiddleware
process_request(self, request) # 请求来了会触发
process_response(self, request, response) # 请求走了会触发

自定义中间件

在应用目录下新建middleware.py文件
1 请求来了触发它,从上往下依次执行(在setting中中间件注册的位置)
from django.utils.deprecation import MiddlewareMixin

class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
            如果返回None,就继续往下走
            如果返回四件套之一,直接就回去了
    
            2 在这里面写请求来了的一些判断
            3 request.META.REMOTE_ADDR  #客户端地址
            4 request.META.HTTP_USER_AGENT  # 客户端类型
          
    def process_response(self, request, response): 
        print('请求走了')
        return response  #一定要return response
        1 请求走了,会触发它,从下往上执行
        2 在所有的响应中都写入cookie name=lqz
        request.set_cookie('name','laz')
        3 在所有的响应头中都写入 response['x-head']='xxx'

process_view(了解)

Django会在调用视图函数之前调用process_view方法。

它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 
如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。
def process_view(self, request, view_func, view_args, view_kwargs):
   # view_func 视图函数
   # view_args,  位置参数
   # view_kwargs 关键字参数
   print('我是process view')

   # 如果return None,会执行执行视图函数
   #手动执行了视图函数
   # response=view_func(request,view_args, view_kwargs)
   # 返回response,视图函数就不执行了
   return HttpResponse('ddddd')

process_exception(了解)

这个方法只有在视图函数中出现异常了才执行
  def process_exception(self, request, exception):
        #记录错误日志
        print(exception)
        print('出错了')

process_template_response(了解)

该方法对视图函数返回值有要求,必须是一个含有render方法类的对象,才会执行此方法

def process_template_response(self,request,response):
    print('我执行了')
    return response
class Test:
    def __init__(self,status,msg):
        self.status=status
        self.msg=msg
    def render(self):
        import json
        dic={'status':self.status,'msg':self.msg}

        return HttpResponse(json.dumps(dic))
def index(response):
    return Test(True,'测试')

CSRF_TOKEN跨站请求伪造

https://www.cnblogs.com/liuqingzheng/p/9505044.html
    
1 CSRF或者XSRF:跨站请求伪造
2 攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的但是却完成了攻击者所期望的一个操作,
比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 
如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户

3 防范:CSRF攻击防范
    Referer:上一次访问的地址(图片防盗链)
        https://www.lagou.com/gongsi/
    - 在请求地址中添加 token 并验证
    - 在 HTTP 头中自定义属性并验证
    - 把随机字符串放在请求体中

从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

  1.登录受信任网站A,并在本地生成Cookie。

  2.在不登出A的情况下,访问危险网站B。

看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:

  1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。

  2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)

  3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

django中处理csrf

1 中间件不要注释了
2 如果是form表单
<form action="" method="post">
    {% csrf_token %}
    <p>给谁转:<input type="text" name="to_user" id="id_name"></p>
    <p>转多少:<input type="text" name="money" id="id_money"></p>
    <input type="submit" value="转账">
</form>
<button class="btn">转帐</button>
3 如果是ajax提交:两种方案
<script>
    $('#btn').click(function () {
        $.ajax({
            url: '/transfer/',
            method: 'post',
            data: {
                user: $('#id_name').val(),
                money: $('#id_money').val(),
                csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
            },
         //  data: {
                user: $('#id_name').val(),
                money: $('#id_money').val(),
                csrfmiddlewaretoken:{{ csrf_token }}
            success: function (data) {
                console.log(data)
            }
        })
    })
</script>   

cookie的处理

获取cookie:document.cookie

是一个字符串,可以自己用js切割,也可以用jquery的插件

获取cookie:$.cookie(‘csrftoken’)

设置cookie:$.cookie(‘key’,’value’)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/jquery.cookie.js"></script> //用jquery的插件
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="text" name="password" id="pwd"></p>
    <p><input type="submit"></p>
</form>
<button class="btn">点我</button>
</body>
<script>
    $(".btn").click(function () {
        var token=$.cookie('csrftoken') // 获取
       
        $.ajax({
            url: '',
            headers:{'X-CSRFToken':token},
            type: 'post',
            data: {
                'name': $('[name="name"]').val(),
                'password': $("#pwd").val(),
            },
            success: function (data) {
                console.log(data)
            }

        })
    })
</script>
</html>

csrf放到请求头中

 $.ajax({
            url: '',
            headers:{'X-CSRFToken':token},
            type: 'post',
            data: {
                'name': $('[name="name"]').val(),
                'password': $("#pwd").val(),
            },
            success: function (data) {
                console.log(data)
            }
        })

全局使用csrf,局部视图函数禁用csrf

1 在视图函数上加装饰器
from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 不再检测,局部禁用(前提是全站使用)
# @csrf_exempt
# 检测,局部使用(前提是全站禁用)
@csrf_protect
def csrf_token(request):
  if request.method=='POST':
        print(request.POST)

        return HttpResponse('ok')
    return render(request,'csrf_token.html')

总结

1 中间件:request对象,response
    -process_request
        -返回None,继续往下走
        -返回response对象,直接返回
    -process_response
        -处理response
    -定义一个类,继承MiddlewareMixin
    -配置文件配置(执行顺序)
2 中间件能干什么
    -全局的登陆认证
    -记录日志(访问日志,登录日志,客户端类型。。。)
    -对ip地址进行限制(一分钟访问十次)
    
3 csrf,xsrf:跨站请求伪造
    
4 django中处理csrf攻击
    1 form表单形式  {% csrf_token %}
    2 ajax提交:手动传,2种方式
    3 ajax提交:放到请求头中
       $.ajax({
            url: '/transfer/',
            headers:{'X-CSRFToken':'sssssss','name':'lqz'},
            method: 'post',
            data: {to_user: $('#id_name').val(), money: $('#id_money').val(),csrfmiddlewaretoken:'{{csrf_token}}'},
            success: function (data) {
                console.log(data)

            }
        })
        
        
4 请求头中的数据,django如何获取
    request.META.get('HTTP_字段名大写')

5 django的csrf中间件
 -全局使用csrf,中间件解开
    -局部禁用:在视图函数上加一个装饰器csrf_exempt
    -全局禁用,中间件加注释
    -局部使用:在视图函数上加一个装饰器csrf_protect
posted @ 2021-12-03 18:03  沈忻凯  阅读(89)  评论(0)    收藏  举报