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

(一)impotlib模块

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

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

  1. 基于Django中间件的思想实现功能的配置使用
  2. 可以通过在settings.py中注释某个字符串来动态取消或增加某个功能的实现
  1. # settings.py
  2. NOTIFY_LIST = [
  3. 'notify.email.Email',
  4. 'notify.msg.Msg',
  5. 'notify.wechat.WeChat',
  6. 'notify.qq.Qq',
  7. ]
  1. # noyify/eamil.py
  2. class Email(object):
  3. def __init__(self):
  4. pass # 发送邮件需要的前期准备
  5. def send(self,content):
  6. print('邮件通知:%s'%content)
  1. # noyify/msg.py
  2. class Msg(object):
  3. def __init__(self):
  4. pass # 发送短信需要的前期准备
  5. def send(self,content):
  6. print('短信通知:%s'%content)
  1. # noyify/wechat.py
  2. class WeChat(object):
  3. def __init__(self):
  4. pass # 发送微信需要的前期准备
  5. def send(self,content):
  6. print('微信通知:%s'%content)
  1. # noyify/__init__.py
  2. import settings
  3. import importlib
  4. def send_all(content):
  5. for path in settings.NOTIFY_LIST:
  6. module_name,cls_name=path.rsplit('.',maxsplit=1) # 因为import最小单位只能到文件,因此需要将文件路径和类名分隔开
  7. module = importlib.import_module(module_name) # 通过importlib导入文件
  8. cls = getattr(module,cls_name) # 通过反射获取文件中类
  9. obj = cls()
  10. obj.send(content)
  1. # start.py
  2. from notify import *
  3. 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值都会不一样

  1. <form action="" method="post">
  2. {% csrf_token %}
  3. <p>username:<input type="text" name="username"></p>
  4. <p>target_account:<input type="text" name="target_user"></p>
  5. <p>money:<input type="text" name="money"></p>
  6. <input type="submit">
  7. </form>
  8. <!--浏览器可以看到的隐藏的input标签-->
  9. <input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">

(三)ajax中的CSRF

(1)通过data携带

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

(2)通过headers携带

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

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

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

  1. static文件夹下新建一个任意名JS文件(setup.js为例),拷贝以下代码
  2. 在页面中导入该js文件
  1. # jswenjian
  2. function getCookie(name) {
  3. var cookieValue = null;
  4. if (document.cookie && document.cookie !== '') {
  5. var cookies = document.cookie.split(';');
  6. for (var i = 0; i < cookies.length; i++) {
  7. var cookie = jQuery.trim(cookies[i]);
  8. // Does this cookie string begin with the name we want?
  9. if (cookie.substring(0, name.length + 1) === (name + '=')) {
  10. cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  11. break;
  12. }
  13. }
  14. }
  15. return cookieValue;
  16. }
  17. var csrftoken = getCookie('csrftoken');
  18. function csrfSafeMethod(method) {
  19. // these HTTP methods do not require CSRF protection
  20. return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  21. }
  22. $.ajaxSetup({
  23. beforeSend: function (xhr, settings) {
  24. if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
  25. xhr.setRequestHeader("X-CSRFToken", csrftoken);
  26. }
  27. }
  28. });

(四)CSRF相关的装饰器

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

(1)MTV模型中使用

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

(2)CBV模型中使用

  1. csrf_protect装饰器CBV中四种装饰器使用方式都可以生效,
  2. csrf_exempt装饰器只能给dispatch装才能生效
  1. # 1. csrf_protect方式全都可以 跟普通的装饰器装饰CBV一致
  2. # @method_decorator(csrf_protect,name='post') # 可以
  3. class MyIndex(views.View):
  4. @method_decorator(csrf_protect)
  5. def dispatch(self, request, *args, **kwargs):
  6. return super().dispatch(request,*args,**kwargs)
  7. def get(self,request):
  8. return render(request,'transfer.html')
  9. # @method_decorator(csrf_protect) # 可以
  10. def post(self,request):
  11. return HttpResponse('OK')
  12. # 2. csrf_exempt这个装饰器只能给dispatch装才能生效
  13. # @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
  14. @method_decorator(csrf_exempt,name='dispatch') # 生效
  15. class MyIndex(views.View):
  16. # @method_decorator(csrf_exempt) # 生效
  17. def dispatch(self, request, *args, **kwargs):
  18. return super().dispatch(request,*args,**kwargs)
  19. def get(self,request):
  20. return render(request,'transfer.html')
  21. # @method_decorator(csrf_exempt,name='post') # csrf_exempt不支持该方法
  22. def post(self,request):
  23. 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
  1. from django.contrib.auth.models import User
  2. # User.objects.create(username=username,password=password) # 不可用 密码不是加密的
  3. # User.objects.create_user(username=username,password=password) # 创建普通用户 密码自动加密
  4. # User.objects.create_superuser(username=username,password=password,email='123@qq.com') # 创建超级用户 需要邮箱数据

(2)校验用户

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

(3)登录保存

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

(4)是否登录

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

(5)检验密码

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

(6)修改密码

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

(7)注销

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

(8)登录检验装饰器

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

    1. 局部配置:直接在括号内添加页面地址
    2. 全局配置:settings文件中配置LOGIN_URL参数
  1. from django.contrib.auth.decorators import login_required
  2. # 局部配置
  3. @login_required(login_url='/login/')
  4. def index(request):
  5. pass
  6. #全局配置
  7. settings配置文件中 直接配置
  8. LOGIN_URL = '/login/'
  9. @login_required
  10. def index(request):
  11. pass
  12. # 如果全局配置了 局部也配置 以局部的为准

(9)User对象的方法

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

(三)扩展默认的auth_user表

(1)一对一外键

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

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

(2)继承

  1. 自定义一个继承内置的AbstractUser的Model类 (需要先导入)
  2. settings配置文件中配置AUTH_USER_MODEL参数(应用名.表名)
  1. # module.py
  2. from django.contrib.auth.models import AbstractUser
  3. class Userinfo(AbstractUser):
  4. phone = models.BigIntegerField()
  5. register_time = models.DateField(auto_now_add=True)
  6. # settings.py
  7. AUTH_USER_MODEL = 'app01.Userinfo' # 应用名.表名

四、Django中settings源码

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

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

五、文件插拔式设计

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

  1. # conf/settings.py
  2. NAME = '我是暴露给用户的自定义配置'
  1. # lib/conf/globa_settings.py
  2. NAME = '我是项目默认的配置文件'
  1. # lib/conf/__init__.py
  2. import importlib
  3. from lib.conf import global_settings
  4. import os
  5. class Settings(object):
  6. def __init__(self):
  7. for name in dir(global_settings):
  8. if name.isupper():
  9. setattr(self, name, getattr(global_settings, name))
  10. # 获取暴露给用户的配置文件字符串路径
  11. module_path = os.environ.get('xxx')
  12. md = importlib.import_module(module_path) # md = settings
  13. for name in dir(md):
  14. if name.isupper():
  15. k = name
  16. v = getattr(md,name)
  17. setattr(self,k,v)
  18. settings = Settings()
  1. # start.py
  2. import os
  3. import sys
  4. BASE_DIR = os.path.dirname(__file__)
  5. sys.path.append(BASE_DIR)
  6. if __name__ == '__main__':
  7. # os.environ.setdefault('xxx','conf.settings')
  8. os.environ['xxx'] = 'conf.settings' # environ是一个字符串所对应环境的映像对象
  9. from lib.conf import settings
  10. 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. Servlet是什么?JSP和Servlet的区别。Servlet的生命周期。

    Servlet(Server Applet),全称Java Servlet, 是用Java编写的服务器端程序.而这些Sevlet都要实现Servlet这个借口.其主要功能在于交互式地浏览和修改数据,生 ...

  2. ES6- Class类的使用,声明,继承

    声明一个类 //class 类 class Coder{ // 类中都是方法 函数 //val是name方法的参数 name(val){ console.log(val) //类 return val ...

  3. 在服务器的tomcat中部署手机apk项目,浏览器或手机下载不能根据URL下载和安装apk文件

    Android的APK包不能下载或安装,需在tomcat的web.xml加入 <mime-mapping>        <extension>apk</extensio ...

  4. Cesium 加载 gltf 模型

    var viewer = new Cesium.Viewer('cesiumContainer', { /*帮助*/ navigationHelpButton: true, baseLayerPick ...

  5. ftp上传文件,上传的文件大小是0

    此问题是最近出现,代码和配置完全没改,试过所有的办法,两天了一直都解决不了,用完弃坑. 防火墙.被动模式主动模式,编码,服务端内存,日志,common-net.jar版本问题,服务端配置,nginx配 ...

  6. SQL Server如何找出一个表包含的页信息(Page)

    在SQL Server中,如何找到一张表或某个索引拥有那些页面(page)呢? 有时候,我们在分析和研究(例如,死锁分析)的时候还真有这样的需求,那么如何做呢? SQL Server 2012提供了一 ...

  7. 官方版vs2008至vs2013下载地址

    Visual Studio 2005 Professional 官方90天试用版 英文版:http://download.microsoft.com/download/e/0/4/e04de840-8 ...

  8. 一条简单的更新语句,MySQL是如何加锁的?

    看如下一条sql语句: # table T (id )) delete : MySQL在执行的过程中,是如何加锁呢? 在看下面这条语句: : 那这条语句呢?其实这其中包含太多知识点了.要回答这两个问题 ...

  9. 如何下载Twitter视频?最简单的保存推特视频的方法

    Twitter上面的短视频越来越流行了,但是推特官方并没有提供下载通道.如果你想下载这些小视频到电脑或者手机(安卓/iPhone),该如何操作呢?下面介绍一种最简单的方法. 下载Twitter视频我们 ...

  10. 【Linux命令】磁盘分区,格式化,挂载命令,创建交换分区(fdisk,mkfs,mount,umount)

    友情链接 磁盘分区,格式化,挂载,创建交换分区:https://www.cnblogs.com/HeiDi-BoKe/p/11936998.html RAID工作级别:https://www.cnbl ...