zoukankan      html  css  js  c++  java
  • day59 csrf auth

    importlib模块

    #bbb.py
    name='from bbb'
    
    #aaa.py
    import importlib
    
    res = 'lib.bbb'
    # 利用字符串的形式导入模块
    md = importlib.import_module(res)  # from lib import bbb
    print(md)  # 该模块字符串最小单位只能到文件名
    # <module 'lib.bbb' from 'D:\pycharm\前端\untitled\import_idea\lib\bbb.py'>
    print(md.name)  # from bbb
    

    基于django中间件的思想 实现功能的配置使用

    通知功能,邮件,短信,微信发送

    #notify.py
    def send_email(content):
        print('邮箱通知%s'%content)
    
    def send_msg(content):
        print('短信通知%s'%content)
    
    def send_wechat(content):
        print('微信通知%s'%content)
    
    #start.py
    from 初级思想.notify import *
    
    def send_all(content):
        send_msg(content)
        send_email(content)
        send_wechat(content)
    if __name__ == '__main__':
            send_all('再坚持一天就周末了')
    

    模仿django

    # notify  email.py
    class Email(object):
        def __init__(self):
            pass #发送邮件需要的前期准备
    
        def send(self,content):
            print('邮件通知:%s'%content)
            
    #notify  msg.py
    class Msg(object):
        def __init__(self):
            pass  # 发送短信需要的前期准备
    
        def send(self, content):
            print('短信通知:%s' % content)
    
    #settings.py
    NOTIFY_LIST=[
        'notify.email.Email',
        'notify.msg.Msg',
        'notify.wechat.WeChat',
        'notify.qq.Qq',
    ]
            
    
    # notify  __init__.py
    import importlib
    import settings
    
    def send_all(content):
        for path in settings.NOTIFY_LIST:#'notify.msg.Msg',
            module_path,cls_name=path.rsplit('.',maxsplit=1)#module_path='notify.msg' cls_name='Msg'
            md=importlib.import_module(module_path)#from notify import email
            cls=getattr(md,cls_name)#通过反射 获取到文件中类的名字
            obj=cls()#实例化一个个类的对象
            obj.send(content)
            
     # start.py
    from notify import *
    
    send_all('好嗨哟')
    

    跨站请求伪造csrf

    钓鱼网站为例:
    写一个跟中国正规网站一模一样的页面,用户输入用户名,密码,对方账户,转账金额,提交。请求确实是朝中国银行发送的,钱也扣了,但是对方账户变了,变成了钓鱼网站提前设置好的账户
    实现:
    在写form表单的时候,让用户填写对方账户input框没有name属性,而是你自己在内部偷偷隐藏了一个具有name属性的input框,并且value值是自己的账户,然后将这个标签隐藏起来
    模拟该现象的产生:创建两个django项目

    解决该问题:
    只处理本网站发送的post请求

    form表单 csrf_token

    <form action="" method="post">
        {% csrf_token %}
        <p>username: <input type="text" name="username"></p>
        <p>target_account: <input type="text" name="target_user"></p>
        <p>money: <input type="text" name="money"></p>
        <input type="submit">
    </form>
    
    在前端显示的是:
    <input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">
    
    

    ajax csrf_token

    方式一

    较为繁琐

    先在页面任意的位置书写{% csrf_token %},然后再发送ajax请求的时候,通过标签查找获取随机字符串添加到data自定义对象即可

    {% csrf_token %}
    <button id="d1">点击发送ajax</button>
    <script>
        $('#d1').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},
                success:function (data) {
                    alert(data)
                }
            })
        })
    </script>
    

    方式二

    较为简单

    {% csrf_token %}
    <button id="d1">点击发送ajax</button>
    <script>
        $('#d1').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
                success:function (data) {
                    alert(data)
                }
            })
        })
    </script>
    

    方式三

    官网提供的文件,是最通用的一种方式,直接新建js文件拷贝代码,导入即可。不需要写任何的csrf相关的代码。

    拷贝地址

    在static里新建一个js文件,再在settings里配置static
    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);
        }
      }
    });
    
    

    在html导入即可

    {% csrf_token %}
    <button id="d1">点击发送ajax</button>
    <script src="/static/setup.js"></script>
    <script>
        $('#d1').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{'username':'jason'},
                success:function (data) {
                    alert(data)
                }
            })
        })
    </script>
    

    csrf相关的装饰器

    csrf_exempt 不校验

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    @csrf_exempt #不校验
    def index(request):
        return HttpResponse('index')
    

    csrf_protect 校验

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    @csrf_protect #校验
    def login(request):
        return HttpResponse('login')
    

    csrf装饰器在CBV上的特例

    csrf_exempt 不校验

    csrf_exempt 这个装饰器只能给dispatch装才能生效

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    from django import views
    from django.utils.decorators import method_decorator
    @method_decorator(csrf_exempt,name='dispatch')
    class MyIndex(views.View):
        # @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
        def get(self,request):
            return render(request,'transfer.html')
    
        def post(self,request):
            return HttpResponse('OK')
    

    csrf_protect 校验

    csrf_protect 方式全部都可以,在哪里都会生效,和普通装饰器装饰CBV一致

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    from django import views
    from django.utils.decorators import method_decorator
    @method_decorator(csrf_protect,name='dispatch')
    class MyIndex(views.View):
        # @method_decorator(csrf_protect)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
        # @method_decorator(csrf_protect)
        def get(self,request):
            return render(request,'transfer.html')
    
        # @method_decorator(csrf_protect)
        def post(self,request):
            return HttpResponse('OK')
    

    django settings源码剖析

    django有两个配置文件
    一个是暴露给用户可以设置的
    一个是内部全局的(用户配置了就用用户的,用户没有配置就用自己的)

    先加载全局配置,给对象设置。然后再加载局部配置,再给对象设置。一旦有重复的项,后者覆盖前者。

    django auth模块

    在使用auth模块的时候 ,要用就用全套

    1.创建用户

    from django.contrib.auth.models import User
    User.objects.create(username=username,password=password)  # 不可用  密码不是加密的
    User.objects.create_user(username=username,password=password)#创建普通用户,密码自动加密
    User.objects.create_superuser(username=username,password=password,email='123@qq.com')#创建超级用户 邮箱也要写入
    

    2.校验用户名和密码是否正确

    from django.contrib import auth
    use_obj=auth.authenticate(request,username=username,password=password)#自动给你加密密码 然后去数据库校验,request可以不写
    必须传用户名和密码 缺一不可
    

    3.保存用户登录状态

    auth.login(request,use_obj)
    '''只要执行了这句话,之后在任意位置通过request.user获取当前登录用户对象'''
    

    4.判断当前用户是否登录

    request.user.is_authenticated()
    

    5.校验原密码是否正确

    request.user.check_password(old_password)#布尔值
    

    6.修改密码

    request.user.set_password(new_password)
    request.user.save()#必须要写
    

    7.注销

    auth.logout(request)
    

    8.检验用户是否登录装饰器

    局部配置

    from django.contrib.auth.decorators import login_required
    # @login_required
    @login_required(login_url='/lgg/')
    

    全局配置

    #settings配置文件中直接配置
    LOGIN_URL='/login/'
    @login_required
    

    扩展auth_user表字段

    方式一

    利用一对一外键字段关系

    class UserDetail(models.Model):
        phone = models.BigIntegerField()
        user = models.OneToOneField(to='User')
    

    方式二

    利用继承关系

    一定要注意 要去配置文件配置
    AUTH_USER_MODEL='app01.Userinfo' #应用名.表名
    这么写完之后,之前所有的auth模块功能全都以建的表为准
    
    from django.contrib.auth.models import AbstractUser
    class Userinfo(AbstractUser):
        phone=models.BigIntegerField()
        register_time=models.DateField(auto_now_add=True)
    
    

    基于配置文件的编程思想

    基于django settings源码实现自己项目配置文件插拔式设计

    #lib  conf __init__
    import importlib
    from lib.conf import global_settings
    import os
    
    class Settings(object):
        def __init__(self):
            for name in dir(global_settings):
                if name.isupper():
                    setattr(self,name,getattr(global_settings,name))
                #获取暴露给用户的配置文件字符串路径
                module_path=os.environ.get('xxx')
                md=importlib.import_module(module_path)
                for name in dir(md):
                    if name.isupper():
                        k=name
                        v=getattr(md,name)
                        setattr(self,k,v)
    setting=Settings()
    
    #lib  conf  global_settings
    NAME = '我是暴露给用户的自定义配置'
    
    #conf settings
    NAME ='我是暴露给用户的自定义配置'
    
    #start
    import os
    import sys
    BASE_DIR = os.path.dirname(__file__)
    sys.path.append(BASE_DIR)
    
    if __name__ == '__main__':
        os.environ['xxx']='conf.settings'
        from lib.conf import settings
        print(settings.NAME)
    
  • 相关阅读:
    python 多核并行计算 示例3,使用 管道 Pipe(仅仅作为记录)
    python 多核并行计算 示例2,使用manager 进行进程共享(仅仅作为记录)
    python 多核并行计算 示例1(工作太忙,仅仅作为记录)
    python多线程示例3,加锁(仅仅作为记录)
    python多线程示例2,加锁(仅仅作为记录)
    python多线程示例1(工作太忙,仅仅作为记录)
    C中字符串分割函数strtok的一个坑(转)
    外扩闪存Quad-SPIFlash(转)
    ARM交叉编译器_说明(转)
    echarts-柱状图-圆柱
  • 原文地址:https://www.cnblogs.com/zqfzqf/p/11992781.html
Copyright © 2011-2022 走看看