Django杂篇(2)
Django杂篇(2)
本文主要介绍cookie与session组件,django中间件以及CSRF的一些介绍.
cookie与session
首先我们要知道,HTTP协议本身是无状态的,无状态的概念是什么?
无状态的意思就是当用户的请求通过HTTP发给后端的时候,HTTP本身是不保留用户的任何状态的,即每次用户发送HTTP都会当做是用户第一次发送数据,这是非常不合理的,试想一下,如果我们登陆一个购物网站,登陆成功之后想要做购买商品,可是是做不了的,因为HTTP无状态,每次登陆都是第一次登陆,我们总是在不停地登陆,就没办法做任何操作.
所以就引出了cookie和session的概念,他们都是用来让用户"保持状态"的,即可以让用户处于登陆状态下,从而进行一系列的操作.
cookie
cookie的实际本体只是一段字符串,他是从服务器发送出来并且存放在浏览器(客户端)上的一组组键值对,当浏览器下次访问服务端的时候,就会在request请求里面自动携带这个字符串,服务端就可以识别这个字符串,根据这个cookie来解析出你的身份,哦,原来我们之前见过,而且进行过一些互动~
查看cookie也非常简单,我们只需要在任何浏览器里面,按F12->找到Network标签->找到下面的二级标签Cookies即可,里面就是当前网页的cookie信息.
那么我们在django里面怎么对cookie做操作呢,实例如下:
# 获取cookie
request.COOKIES.get('key')#因为cookie其实是一个字典,所以用get取值比较好,取值时候尽量不要用中括号取值,因为中括号取值如果取不到会报错,影响整个项目的运行
# 设置cookie
# 要先取到一个对象,可以是HttpResponse(),也可以是render()或者redirect()
obj = HttpResponse()
obj.set_cookie(key,value...)
# 删除cookie
# 同样需要先取到一个对象,然后对其做操作
obj = HttpResponse()
obj.delete_cookies("key")
session
既然我们已经有了cookie这个可以保持用户状态的工具,为什么还要引入session的概念呢?大致原因有以下两条:
- cookie本身支持的长度较小,最大只支持4096字节,不足以支持非常大的项目以及用户量
- cookie本身存在浏览器(客户端),我们知道存在于浏览器的数据是公开的,并不安全,使用者可以随时更改或者拦截这些数据,从而拿着这些cookie来做非法的事情,不太安全
所以,为了解决以上两个问题,我们引入了session的概念,一方面session可以支持更大的数据,另一方面session是存放于服务端的,安全性比存放于浏览器的cookie要高得多.
话虽如此,但其实session并不是取代cookie而存在的东西,而是共存的事物,因为cookie解决的是HTTP协议的无状态的问题,让服务端知道来的用户是谁,然后我们通过cookie识别不同的用户,进而在服务端的session里面保存该用户私密的信息,以及那些长度超过cookie限制的文本数据.
另外要注意一点的是,在django里面的session的产生是针对同一台机器的不同浏览器而言的,即我们使用同一台机器的同一个浏览器在后端的数据库表里永远只会有一条session记录,新生成的会把旧的覆盖掉,只有我们更换浏览器或者更换机器才会生成两条不同的session记录.
下面介绍我们怎么样在django里面对session操作
# 获取session
request.session.get('key',None)
# 一样用get取值,如果值不存在就返回None
request.session.session_key
# 可以获取该会话session的key值
# 设置session值
request.session['key']=value
request.session.setdefault('key',value)
# 可以直接用key,value的方式进行赋值,setdefault的优势在于如果设置的值已经存在则不会改变原值,如果不存在就会添加值
request.session.set_expiry(value=)
'''可以配置session的有效时间,里面的参数value有多种写法
1. 如果写的是数字,就是按秒计算有效时间,数字即为秒数
2. 如果为0,则session在关闭浏览器后就会失效,即只会生效在当前打开的浏览器中
3. 如果为空白,就会使用django默认的时间,即14天的有效时间
4. 如果为是一个datetime或者timedelta时间,则会在这个时间后失效
'''
# 删除session值
del request.session['key']
request.session.delete() #只会删除服务端的session
request.session.flush() #会同时删除服务端的session和客户端的cookie
使用session还有一个好处:客户端只有cookie的值,并不能直接看到用户的信息,而后端的session是依赖于cookie的,所以这里就形成了一个前后端分离的状态,cookie保存在客户端,session保存在服务端,极大提升了数据的安全性.
django中间件
首先,我们要了解什么是中间件?
就名字来看,中间件就是中间的一个组件,我们可以把我们整个后端看成一个学校,那么中间件就是学校的门卫室,不管用户的请求进入后端或者是从后端出来,都要经过中间件的检查,检查不通过就无法继续交互.
上面是按照生活中的看法来说的,就官方的说法来说,中间件就是一个钩子,一个用来处理Django的请求和响应的钩子,可以用来控制全局范围内Django的输入和输出,常用的中间件有七个,每个中间件都会负责一些特定的功能,且这些功能大多生效在视图函数的执行之前或者执行之后,中间件的本质还是一个类,以类中定义方法的形式来限制Django的输入和输出的格式.
其实我们之前已经接触过中间件,只不过当时我们都是把其中的一条注释掉,因为不注释的话会影响我们程序的正常运行,自今天起我们就不用做注释掉这么low的操作了,我们可以光明正大的去使用并且可以尝试自己写中间件了.
首先我们要知道中间件在哪里,在settings.py文件里,如下:
# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 首先,该配置项是一个列表,请求在经过中间件的时候是从上到下进入这些方法进行判断的
# 以上就是系统默认的七个中间件,当然我们可以手动写一个属于自己的中间件,当然,在自己写中间件之前,我们要先了解一下这些中间件都包含有什么方法,以及是怎么运作的
自定义中间件
我们先来看如何自定义中间件:
首先我们需要新建一个文件夹(这里我们命名为mymiddleware),任意名字都可以,然后里面建一个任意名字的py文件(这里我们命名为myaabb.py),里面写一个类,有固定的继承的父类
#/app01/mymiddleware/myaabb/
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
...
建立好类之后,我们还需要去settings.py文件里面注册,注册非常简单,就是把我们创建这个文件夹和文件的路径写入MIDDLEWARE的列表里就可以了.
# settings.py
MIDDLEWARE = [
'app01.mymiddleware.myaabb.MyMiddlel',
]
下面我们就可以在我们自定义的文件中定义类和写我们需要的方法了,其实中间件里面常用的自定义方法只有五个,每个中间件里所定义的方法也都在这五个方法之内,如下:
'''
1.process_request:该方法是请求来的时候自动触发,要注意点,在该方法内如果有return HTTPResponse(),那么之后的中间件都不会再执行,会执行同一级别的process_response,然后从该中间件直接返回,实例如下
'''
def process_request(self,request):
print('我是自定义中间件里面的process_request方法')
return HttpResponse("我是自定义中间件里面的HttpResponse对象返回值") # 直接原地返回
'''
2.process_response:该方法是响应走的时候调用的,即请求在经过了中间件,urls,views之后,返回值再次走到中间件的时候会调用process_response,且调用顺序是从下到上,即MIDDLEWARE里面从下到上的调用每个中间件的process_response
'''
def process_response(self,request,response): # response就是要返回给用户的数据
print("我是第一个自定义中间件里面的process_response方法")
return response # 这里要注意,凡是形参里面带有response的,最后一定要return response,否则返回值数据会丢失
'''
3. process_view:会在路由(urls.py)匹配成功之后执行视图函数(views.py)之前触发
4. process_exception:当视图函数(views.py)出现bug的时候自动触发
5. process_template_response:当视图函数执行完毕之后并且返回的对象中含有render方法的情况下才会触发(最不常用)
'''
跨站请求伪造(csrf)
跨站请求伪造,全称(Cross-site request forgery),可能我们会对这个名字比较陌生,但是换个叫法我们就熟悉了,钓鱼网站.简单来说就是欺骗用户的浏览器,让其以用户的名义运行操作,达到制作钓鱼网站的人的目的.
CSRF的解决方案
CSRF最常用的解决方案即是添加一个校验用token,改数据不保存在cookie中,且攻击者很难伪造,token其本质就是一串随机数,是由服务端生成并发给客户端的,在客户端提交数据的时候会随着数据一起提交,供服务端来校验,校验通过才会接收客户端的请求并做处理,若token错误或为空,服务端就会拒绝这个请求
添加校验token
FORM表单添加
form表单添加token非常简单,在form表单的内部直接加上{% csrf_token %}
即可,在任何位置都可以.
AJAX添加
AJAX添加token的方法常用的有三种
# 1. 通过标签查找并添加
data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()}
# 2. 通过django的模板语法来添加,这种方法用处有限,因为如果前后端分离的话,后端可能不会用django来搭建,所以模板语法也就不能使用了.
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}
# 3. 拷贝一个js文件,然后导入到前端的html文件里即可,这里我们新建static文件夹,并在里面新建一个setup.js文件然后粘贴以下代码
# /static/setup.js
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);
}
}
});
# 完成之后我们还需要配置两个地方,一个就是settings.py,一个就是我们的html文件里,AJAX的上方
# settings.py
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static')
]
# **.html,直接导入该js文件即可
<script src="/static/setup.js"></script>
装饰器方式
装饰器方式主要是用于CBV上,且使用时候要注意
- csrf_exempt只能用于CBV里面的dispatch方法上面,不能用于别的方法
- 除了csrf_exempt之外,其他所有的装饰器都可以加在不同的方法上,比如get或者post
比如:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
# csrf_exempt 只能用于装饰dispatch
# 第一种
# @method_decorator(csrf_exempt,name='dispatch')
class MyCsrf(View):
# 第二种
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
# 除了csrf_exempt之外 所有的其他装饰器 在CBV上面都有三种方式,即在类外部,或者类内部的方法上方
@method_decorator(csrf_protect,name='post')
class MyCsrf(View):
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
@method_decorator(csrf_protect)
def post(self,request):
return HttpResponse('post')
Django杂篇(2)的更多相关文章
- Django杂篇(1)
目录 Django杂篇(1) bulk_create Pagination 创建多对多表关系的常用方法 form校验组件的应用 渲染页面 展示错误信息 校验数据 常用字段 Django杂篇(1) 这里 ...
- 异步任务队列Celery在Django中的使用
前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...
- 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...
- django server之间通过remote user 相互调用
首先,场景是这样的:存在两个django web应用,并且两个应用存在一定的联系.某些情况下彼此需要获取对方的数据. 但是我们的应用肯经都会有对应的鉴权机制.不会让人家随随便便就访问的对吧.好比上车要 ...
- Mysql事务探索及其在Django中的实践(二)
继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...
- Mysql事务探索及其在Django中的实践(一)
前言 很早就有想开始写博客的想法,一方面是对自己近期所学知识的一些总结.沉淀,方便以后对过去的知识进行梳理.追溯,一方面也希望能通过博客来认识更多相同技术圈的朋友.所幸近期通过了博客园的申请,那么今天 ...
- 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...
- 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...
- 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...
随机推荐
- StringUtils工具类常用api <转>
该工具类是用于操作Java.lang.String类的. StringUtils类与String类的区别在于:此类是null安全的,即如果输入参数String为null,则不会抛出NullPointe ...
- 异或空间求基(模板)——hdu3949
输出样例有点问题的.. #include<bits/stdc++.h> using namespace std; #define ll unsigned long long #define ...
- LUOGU P3723 [AH2017/HNOI2017]礼物 (fft)
传送门 解题思路 首先我们设变化量为\(r\),那么最终的答案就可以写成 : \[ ans=min(\sum\limits_{i=1}^n(a_i-b_i+r)^2) \] \[ ans=min(\s ...
- Python内置的一个用于命令项选项与参数解析的模块argparse
一.argparse简单使用 我们先来看一个简单示例.主要有三个步骤: 创建 ArgumentParser() 对象 调用 add_argument() 方法添加参数 使用 parse_args() ...
- C语言-实例3个数由小到大排序
VS2012 //C语言实例 3个数由小到大排序 #include <stdio.h> void main() { int a, b, c, t; printf("Please ...
- windows中创建流量转发规则
#创建流量转发,其中listenaddress为内网ip(也就是ipconfig中所显示的IP),listenport为监听的本机对外端口,后两个分别是需转发的目标主机IP和端口. netsh int ...
- Spark 调优之ShuffleManager、Shuffle
Shuffle 概述 影响Spark性能的大BOSS就是shuffle,因为该环节包含了大量的磁盘IO.序列化.网络数据传输等操作. 因此,如果要让作业的性能更上一层楼,就有必要对 shuffle 过 ...
- 牛客练习赛43D Tachibana Kanade Loves Sequence
题目链接:https://ac.nowcoder.com/acm/contest/548/D 题目大意 略 分析 贪心,首先小于等于 1 的数肯定不会被选到,因为选择一个数的代价是 1,必须选择大于1 ...
- rmReport 自适应行高(自动行高)
这个问题 1.先中主项数据--属性--stretched(伸展):true 选中主项数据中的所有列--属性--其他属性--自动折行 --伸展
- I Love Palindrome String HDU - 6599 回文树+hash
题意: 输出每个长度下的回文串(这些回文串的左半边也需要是回文串) 题解: 直接套上回文树,然后每找到一个回文串就将他hash. 因为符合要求的回文串本身是回文串,左半边也是回文串,所以它左半边也右半 ...