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)
    
  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/zqfzqf/p/11992781.html
Copyright © 2011-2022 走看看