一、模拟实现中间件的编程思想

(一)impotlib模块

  1. importlib模块可以通过字符串的形式导入模块
  2. importlib模块也支持notify.email的from···import类型
  3. 最小单位只能到文件名,不能用来导入文件中的变量名
# importlib模块(以导入json模块为例)
import importlib
json = importlib.import_module('json')

module = importlib.import_module('notify.email')

(二)实现功能的配置使用

  1. 基于Django中间件的思想实现功能的配置使用
  2. 可以通过在settings.py中注释某个字符串来动态取消或增加某个功能的实现
# settings.py
NOTIFY_LIST = [
    'notify.email.Email',
    'notify.msg.Msg',
    'notify.wechat.WeChat',
    'notify.qq.Qq',
]
# noyify/eamil.py
class Email(object):
    def __init__(self):
        pass  # 发送邮件需要的前期准备

    def send(self,content):
        print('邮件通知:%s'%content)
# noyify/msg.py
class Msg(object):
    def __init__(self):
        pass  # 发送短信需要的前期准备

    def send(self,content):
        print('短信通知:%s'%content)
# noyify/wechat.py
class WeChat(object):
    def __init__(self):
        pass  # 发送微信需要的前期准备

    def send(self,content):
        print('微信通知:%s'%content)
# noyify/__init__.py
import settings
import importlib

def send_all(content):
    for path in settings.NOTIFY_LIST:
        module_name,cls_name=path.rsplit('.',maxsplit=1)  # 因为import最小单位只能到文件,因此需要将文件路径和类名分隔开
        module = importlib.import_module(module_name)  # 通过importlib导入文件
        cls = getattr(module,cls_name)  # 通过反射获取文件中类
        obj = cls()
        obj.send(content)      
# start.py
from notify import *
send_all('明天放假')

二、跨站请求伪造CSRF

(一)由来

以钓鱼网站的转账为例:

  1. 做一个假的网站,使得用户填写的对方账户iniput标签没有name属性
  2. 在内部隐藏一个具有name属性input标签,value为自己的账户
  3. 此时提交时,后端获取的目标账户是自己的账户,从而形成钓鱼

因此,CSRF就是为了解决这种问题

  1. 网站在返回用户form表单时,自动隐藏一个input标签,该标签value为一个随机的字符串
  2. 每一个浏览器发送的随机字符串都是独一无二的
  3. 从而解决这种调阅问题

(二)form表单的CSRF

  1. 只需要在表单中写一个{% csrf_token %}

  2. 浏览器中的隐藏input标签中name="csrfmiddlewaretoken"

  3. 每一次刷新,value值都会不一样

<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标签-->
<input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">

(三)ajax中的CSRF

(1)通过data携带

  1. 在html页面任意地方书写{% csrf_token %}
  2. 通过标签查找将随机字符串添加到ajax的data对象中或者直接调用模板语法即可
data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},

data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}, 

(2)通过headers携带

通过获取返回的cookie中字符串,放置在请求头中

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  headers: {"X-CSRFToken": $.cookie('csrftoken')},  // 从Cookie取csrf_token,并设置ajax请求头
  data: {"username": "Q1mi", "password": 123456},
  success: function (data) {
    console.log(data);
  }
})

(3)官网提供的文件(推荐用法)

  1. static文件夹下新建一个任意名JS文件(setup.js为例),拷贝以下代码
  2. 在页面中导入该js文件
# jswenjian
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);
    }
  }
});

(四)CSRF相关的装饰器

  1. 局部:CSRF相关的装饰器用于局部设置或取消CSRF验证
  2. 全局: 通过中间件 django.middleware.csrf.CsrfViewMiddleware 来设置或取消CSRF校验

(1)MTV模型中使用

  1. 需要先导入装饰器
  2. @csrf_protect :设置被装饰函数的CSRF(跨站请求伪造)校验
  3. @csrf_exempt:取消被装饰函数的CSRF(跨站请求伪造)取消
from django.views.decorators.csrf import csrf_exempt,csrf_protect

(2)CBV模型中使用

  1. csrf_protect装饰器CBV中四种装饰器使用方式都可以生效,
  2. csrf_exempt装饰器只能给dispatch装才能生效
# 1. csrf_protect方式全都可以  跟普通的装饰器装饰CBV一致
# @method_decorator(csrf_protect,name='post')  # 可以
class MyIndex(views.View):
    @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def get(self,request):
        return render(request,'transfer.html')
    # @method_decorator(csrf_protect)  # 可以
    def post(self,request):
        return HttpResponse('OK')

# 2. csrf_exempt这个装饰器只能给dispatch装才能生效
# @method_decorator(csrf_exempt,name='post')  # csrf_exempt不支持该方法
@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')
    # @method_decorator(csrf_exempt,name='post')  # csrf_exempt不支持该方法
    def post(self,request):
        return HttpResponse('OK')   

三、Django中auth模块

(一)什么是auth模块

  1. auth模块是Django自带的用户认证模块,可以实现包括用户登录、注册、认证、注销、修改密码等功能
  2. 默认使用auth_user表存储用户数据
  3. 使用之前先导入from django.contrib import auth

(二)常用方法

(1)创建用户

  1. create_superuser(): 创建超级用户 ,必要参数username、password、email
  2. create_user():创建普通用户,必要参数username、password
  3. 终端中输入命令:python manage.py createsuperuser
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)校验用户

  • authenticate(): 验证用户名以及密码是否正确 , 需要username 、password两个关键字参数 ,正确返回User对象,否则为空
from django.contrib import auth
user_obj = auth.authenticate(request,username=username,password=password)
# 必须传用户名和密码两个参数缺一不能

(3)登录保存

  • login(HttpRequest, user):用户登录并保存状态,保存后可以通过request.user中获取当前登录用户对象
auth.login(request,user_obj)
# 只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过request.user获取到当前登录的用户对象

(4)是否登录

  • is_authenticated(): 判断当前请求是否通过了认证
request.user.is_authenticated()

(5)检验密码

  • check_password(password): 检查密码是否正确的方法,需要提供当前请求用户的密码 ,返回布尔值
request.user.check_password(old_password)

(6)修改密码

  • set_password(password):设置密码,修改完之后一定记得使用save保存
request.user.set_password(new_password)
request.user.save()  # 千万不要忘了

(7)注销

  • logout(request): 清除当前请求的全部session信息, 无返回值
auth.logout(request)

(8)登录检验装饰器

  • login_requierd(): 一个登录校验的装饰器,可以添加变量login_url指定没有登录情况下跳转的页面

    1. 局部配置:直接在括号内添加页面地址
    2. 全局配置:settings文件中配置LOGIN_URL参数
from django.contrib.auth.decorators import login_required
# 局部配置
    @login_required(login_url='/login/')
    def index(request):
        pass

#全局配置
settings配置文件中 直接配置
LOGIN_URL = '/login/'

@login_required
def index(request):
    pass
# 如果全局配置了 局部也配置  以局部的为准

(9)User对象的方法

  1. i s_staff : 用户是否拥有网站的管理权限
  2. is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。

(三)扩展默认的auth_user表

(1)一对一外键

通过一对一外键字段关系扩展字段

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

(2)继承

  1. 自定义一个继承内置的AbstractUser的Model类 (需要先导入)
  2. settings配置文件中配置AUTH_USER_MODEL参数(应用名.表名)
# module.py
from django.contrib.auth.models import AbstractUser

class Userinfo(AbstractUser):
phone = models.BigIntegerField()
register_time = models.DateField(auto_now_add=True)

# settings.py
AUTH_USER_MODEL = 'app01.Userinfo'  # 应用名.表名

四、Django中settings源码

  1. Django中有两个配置文件,一个内部全局的,一个用户自定义
  2. 如果用户配置了,就使用该配置,否则使用内部全局设置

实现思路:先加载全局配置给对象设置,然后在加载局部配置 再给对象设置,一旦有重复的项 后者覆盖前者

五、文件插拔式设计

基于settings源码设计思想启发,实现文件插拔式设计

# conf/settings.py
NAME = '我是暴露给用户的自定义配置'
# lib/conf/globa_settings.py
NAME = '我是项目默认的配置文件'
# lib/conf/__init__.py

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)  # md = settings
        for name in dir(md):
            if name.isupper():
                k = name
                v = getattr(md,name)
                setattr(self,k,v)

settings = Settings()
# start.py
import os
import sys

BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)

if __name__ == '__main__':
    # os.environ.setdefault('xxx','conf.settings')
    os.environ['xxx'] = 'conf.settings'  # environ是一个字符串所对应环境的映像对象
    from lib.conf import settings
    print(settings.NAME)

(day59)十一、CSRF、Auth模块、impotlib模块、settings源码的更多相关文章

  1. 跨站请求伪造(csrf),django的settings源码剖析,django的auth模块

    目录 一.跨站请求伪造(csrf) 1. 什么是csrf 2. 钓鱼网站原理 3. 如何解决csrf (1)思路: (2)实现方法 (3)实现的具体代码 3. csrf相关的装饰器 (1)csrf_p ...

  2. django 之csrf、auth模块及settings源码、插拔式设计

    目录 基于django中间件拷贝思想 跨站请求伪造简介 跨站请求伪造解决思路 方式1:form表单发post请求解决方法 方式2:ajax发post请求解决方法 csrf相关的两个装饰器 csrf装饰 ...

  3. Django对中间件的调用思想、csrf中间件详细介绍、Django settings源码剖析、Django的Auth模块

    目录 使用Django对中间件的调用思想完成自己的功能 功能要求 importlib模块介绍 功能的实现 csrf中间件详细介绍 跨站请求伪造 Django csrf中间件 form表单 ajax c ...

  4. django----csrf跨站请求伪造 auth组件 settings源码 importlib模块

    目录 importlib模块 csrf跨站请求伪造 form表单发送 ajax发送 csrf装饰器 auth模块 如何创建超级用户(root) 创建用户 校验用户名和密码是否正确 保存用户登录状态 判 ...

  5. Django的View(视图)-settings源码的解析-模板层-模板语法

    FBV与CBV 视图函数并不只是指函数,也可以是类 FBV:基于函数的视图,类似面向函数式编程 CBV:基于类的视图,类似面向对象编程 研究解析render源码: render:返回html页面:并且 ...

  6. Django学习——Django settings 源码、模板语法之传值、模板语法之获取值、模板语法之过滤器、模板语法之标签、自定义过滤器、标签、inclusion_tag、模板的导入、模板的继承

    Django settings 源码 """ 1.django其实有两个配置文件 一个是暴露给用户可以自定义的配置文件 项目根目录下的settings.py 一个是项目默 ...

  7. Django的settings源码分析

    Django其实有两个配置文件,一个是暴露给用户的可以自定义的配置,一个是项目默认的配置,用户如果配置了就用用户的,没有配置就用默认的. 首先需要在settings文件中导入,然后查看settings ...

  8. Django settings源码解析

    Django settings源码 Django中有两个配置文件 局部配置:配置文件settings.py,即项目同名文件夹下的settings.py文件 全局配置:django内部全局的配置文件se ...

  9. abp vnext2.0之核心组件模块加载系统源码解析与简单应用

    abp vnext是abp官方在abp的基础之上构建的微服务架构,说实话,看完核心组件源码的时候,很兴奋,整个框架将组件化的细想运用的很好,真的超级解耦.老版整个框架依赖Castle的问题,vnext ...

随机推荐

  1. python3抓取淘宝评论内容

    好久没有写爬虫了,今天研究了下淘宝商品评论的内容. 一开始用最简单的方法,挂代理,加请求头,对网页请求,是抓不到数据的,在网上找了一些相关文章,也基本已经过时了,就是网站逻辑有改动,用旧的方法是抓不到 ...

  2. 基于Redis消息的订阅发布应用场景

    目录 基于Redis消息的订阅发布应用场景 1.应用背景 2.困境 2.1 锁表风险 2.2 实时性差 2.3 增加编程复杂性 2.4 实时效果 3.解决方案 3.1 前端传值给服务端 3.2 服务端 ...

  3. postgreSQL安装教程 Windows

    Windows 上安装 PostgreSQL 这里使用 EnterpriseDB 来下载安装,EnterpriseDB 是全球唯一一家提供基于 PostgreSQL 企业级产品与服务的厂商. 下载地址 ...

  4. Dynamics 365 Customer Engagement V9.X新引入的自动编号属性介绍

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  5. Python—定时任务(APScheduler实现)

    简介                 APScheduler的全称是Advanced Python Scheduler.它是一个轻量级的基于Quartz的 Python 定时任务调度框架.APSche ...

  6. fiddler 进行Android/IOS代理配置抓包

    1.准备:Android+IOS设备 下载:fiddler抓包工具,不是最新版的链接:   链接:https://pan.baidu.com/s/1BaBfu2H4xgpsh1wmkfC8aQ     ...

  7. 洛谷 UVA1328 Period

    洛谷 UVA1328 Period 洛谷传送门 题目描述 PDF 输入格式 无 输出格式 无 题意翻译 题意描述 对于给定字符串S的每个前缀,我们想知道它是否为周期串.也就还是说,它是否为某一字符串重 ...

  8. JQ的offset().top与JS的getBoundingClientRect区别详解,JS获取元素距离视窗顶部可变距离

     壹 ❀ 引 我在 JQ的offset().top与js的offsetTop区别详解 这篇博客中详细分析了JQ方法offset().top与JS属性offsetTop的区别,并得出了一条offset( ...

  9. 浅谈Kotlin中的函数

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/UV23Uw_969oVhiOdo4ZKAw作者:连凌能 Kotlin,已经被Android官方 ...

  10. github仓库迁移到gitlab以及gitlab仓库迁移到另一个gitlab服务器

    一. github仓库迁移到gitlab 先进入 new project: 选择 Import project, 选择下面的github: 进入后,这里需要github的 personal acces ...