Django(六)Session、CSRF、中间件
大纲
二、session
1、session与cookie对比
2、session基本原理及流程
3、session服务器操作(获取值、设置值、清空值)
4、session通用配置(在配置文件中)
5、session引擎配置(db、cache、file、cookie加密)
三、CSRF
1、csrf原理-form提交及ajax提交
2、csrf全局与局部应用配置
四、中间件生命周期
1、process_request、process_response
下面自己创建一个中间件
2、process_view
3、其他
一、内容回顾
二、session
1、session与cookie对比
Cookie:保存在用户浏览器端的键值对
本地可以修改;如果有敏感信息,可以被看到。
基于cookie做用户验证时,敏感信息不适合放在cookie中
把存储压力放到每个客户端上,对于服务器端压力小了。
Session:保存在服务器端的键值对
服务端:保存键值对{'随机字符串':{……用户信息……}},通过cookie保存随机字符串到客户端上。
使用session前:先执行 python manage.py makemigrations , python manage.py migrate,因为默认Django session 保存在数据库中的django_session表中。
2、session基本原理及流程
session 设置值
request.session['is_login'] = TrueDjango会执行一下操作
# 生成随机字符串
# 写到用户浏览器cookie
# 保存到session中
# 在随机字符串对应的字典中设置相关内容……
session 获取值
request.session['is_login']:执行以下操作
# 获取当前用户的随机字符串
# 根据随机字符串获取对应信息
- 使用session前,别忘了先生成数据库
python manage.py migrate
urls.py
url(r'^login/', views.login),
url(r'^index/', views.index),
url(r'^logout/$', views.logout),
views.py
def login(request):
if request.method == "GET":
return render(request,'login.html')
elif request.method == "POST":
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'root' and pwd == "":
# session中设置值
# 生成随机字符串
# 写到用户浏览器cookie
# 保存到session中
# 在随机字符串对应的字典中设置相关内容……
request.session['username'] = user
request.session['is_login'] = True
if request.POST.get('rmb',None) == '':
# 超时时间
request.session.set_expiry(10)
return redirect('/index/')
else:
return render(request,'login.html') def index(request):
# 获取当前用户的随机字符串
# 根据随机字符串获取对应信息
if request.session.get('is_login',None):
return HttpResponse(request.session['username'])
else:
return HttpResponse("请登录……") def logout(request):
# del request.session['username']
request.session.clear() # 清除session,注销
return redirect('/login/')
login.html
<body>
<form action="/login/" method="POST">
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="rmb" value="1" /> 10秒免登录
<input type="submit" value="提交" />
</form>
</body>>
index.html
<body>
<h1>欢迎登录:{{ username }}, {{ request.session.username }}</h1>
<!---------- 这里不用使用后台模板传值,使用session也能获取到用户名 -------------->
<a href="/logout/">注销</a>
</body>
3、session服务器操作(获取值、设置值、清空值)
# 获取、设置、删除Session中数据
request.session['k1'] # 获取
request.session.get('k1',None)
request.session['k1'] = 123 # 设置
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1'] # 删除 # 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems() # 获取用户session的随机字符串
request.session.session_key
# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()
# 检查 用户session的随机字符串 在数据库中是否存在
request.session.exists("session_key")
# 删除当前用户的所有Session数据
request.session.delete("session_key")
request.session.clear() # 比delete用法更简单,注销的时候可以使用 # 设置超时时间 (默认session超时时间是两周)
request.session.set_expiry(value)
# * 如果value是个整数,session会在些秒数后失效。
# * 如果value是个datatime或timedelta,session就会在这个时间后失效。
# * 如果value是0,用户关闭浏览器session就会失效。
# * 如果value是None,session会依赖全局session失效策略。
4、session通用配置(在配置文件中)
settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
# 这个好。settings里设为true,超时时间按照最后一次客户端请求计算,如上按照最后一次请求之后10秒失效。
5、session引擎配置(db、cache、file、cookie加密)
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
- 数据库(默认)
- 缓存
- 文件
- 缓存+数据库
- 加密cookie
# 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) # 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
# 连接memcache 的配置,缓存部分会提到。不支持redis,连它需要安装插件 # 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = os.path.join(BASE_DIR, 'cache') # 放到cache目录下
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
# 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T # 缓存+数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 # 加密cookie Session (都放到cookie里面,只是做了加密处理)
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
三、CSRF
之前提到的xss攻击:网站评论里等允许别人写js的时候,别人进行的恶意操作。csrf类似。
CSRF的防护通常有两种方式,一个是通过Challenge-Response的方式,例如通过Captcha和重新输入密码等方式来验证请求是否伪造,但这会影响用户体验,类似银行付款会采用这样的方式。另一种是通过随机Token的方式,多数Web系统都会采用这种方式,Django也是用的这种。
1、csrf原理-form提交及ajax提交
客户端get请求时,django会生成随机字符串给客户,当客户端提交form表单的时候,如果没有随机字符串,则django不允许,报403错误。
form提交数据需要带随机字符串过去,Ajax提交也需要带着过去。ajax带哪的值?
加上{% csrf_token %}在html form里生成了一个,在也生成了一份。浏览器审查元素 –> Network –> Cookies 里也能找到随机字符串。
所以ajax提交的时候,只需要把cookie里的随机字符串拿到,放到请求头里面发过去就可以了
后台获取随机字符串的key,key是什么值? x-CSRFtoken
login.html
<body>
<!-- form 提交 -->
<form action="/login/" method="POST">
<!-- 生成 csrf 的随机字符串 -->
<!-- {{ csrf_token }} -->
{% csrf_token %} <!--html里会自动生成隐藏input框-->
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="rmb" value="1" /> 10秒免登录
<input type="submit" value="提交" />
<input id="btn" type="button" value="Ajax提交" />
</form> <script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function(){
// ajax 提交
$.ajaxSetup({ // 对整个页面所有的ajax操作做个配置
beforeSend: function(xhr,settings){ // 发送ajax前的操作
xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
}
}); $('#btn').click(function () {
$.ajax({
url: '/login/',
type:"POST",
data: {'user': 'root', 'pwd': '123'},
// 这种方式加请求头,每个操作都加麻烦一些,所以使用上面的 ajaxSetup 里加
// headers: {'X-CSRFtoken': $.cookie('csrftoken')},
success:function(arg){ }
})
});
})
</script>
</body>
这里ajax提交,在浏览器审查元素、network里看效果。
2、csrf全局与局部应用配置
settings里面,允许csrf验证,那么就是对全局都进行验证。如果个别的方法不需要使用,怎么单一配置?
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
对于ajax中,采用ajaxSetup方式也是全局都加,比如get方式是不需要的,可以如下配置
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
// settings 会获取到ajax里面的所有配置
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
function Do(){
$.ajax({
url:"/app01/test/",
data:{id:1},
type:'POST',
success:function(data){
console.log(data);
}
});
}
四、中间件生命周期
settings里的 MIDDLEWARE 都是一个一个的中间件。客户端请求,先经过一排一排的中间件到达views,之后再通过中间件返回给客户端。而通过中间件都是调用中间件的某个方法、
1、process_request、process_response
- process_request:客户端请求,经过中间件的方法
- process_response:返回客户端,经过中间件的方法
下面自己创建一个中间件
随便创建一个目录middle,
middle/m.py
from django.utils.deprecation import MiddlewareMixin class Row1(MiddlewareMixin):
def process_request(self, request):
print("中间件1")
def process_response(self, request, response):
print("中间件1返回")
return response
# 参数里的 response :就是views里面返回的值,所以要继续返回一下,否则客户端收不到数据
from django.shortcuts import HttpResponse
class Row2(MiddlewareMixin):
def process_request(self, request):
print("中间件2")
# return HttpResponse("禁止你访问")
def process_response(self, request, response):
print("中间件2返回")
return response class Row3(MiddlewareMixin):
def process_request(self, request):
print("中间件3")
def process_response(self, request, response):
print("中间件3返回")
return response
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',
'middle.m.Row1',
'middle.m.Row2',
'middle.m.Row3',
]
views.py
def test(request):
print("最终返回信息")
return HttpResponse("OK")
中间件里面的参数request里接受的数据和views里接受的数据是一样的,所以从里面取值可以做相应的判断处理,允不允许数据通过。
比如上面的示例:中间件row2,process_request,里返回数据,则会在同级的process_response里开始返回数据给客户端了。
注意:这是在Django1.10版本才这样的,之前版本:row2返回数据,会在最底部的response开始网上返回数据,这里是row3。
所以中间件是对所有的请求做统一操作,比如数据校验、黑名单过滤
2、process_view
如下:每个中间件类中中加入如下方法:
class Row1(MiddlewareMixin):
def process_request(self, request):
print("中间件1")
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
# view_func 对应 views函数,view_func_args、kwargs 对应 views里的参数、
print("中间件1view")
def process_response(self, request, response):
print("中间件1返回")
return response
请求顺序如下:用户请求 –> 每个中间件的request –> 到达urls路由匹配,匹配成功后 –> 折回每个中间件的view –> views –> 通过response返回
3、其他
def process_exception(self, request, exception):
if isinstance(exception, ValueError):
return HttpResponse("出现异常")
# 异常处理 views函数里出错了,执行这里,如views里 int('lgeng')
views函数如果出现异常,返回会找exception方法,一级一级往上找,如果有处理返回,如果都没有处理就直接返回报错了。
process_template_response(self,request,response)
# 如果views中的函数返回的对象中,具有render方法,执行这个方法。
一、内容回顾
1、基本生命周期
2、URL
/index/ index
/list/(\d+) index
/list/(\d+) name='li' index
/list/(\d+) include index
3、views
# 所有内容的原生值
request.body # 所有的post请求,都会放到body里面传过去
request.POST # 从request.body中提取
request.GET # 从request.body中提取
request.FILES
request.xxxx.getlist
# 请求头内容
request.Meta
request.method(POST,GET,PUT)
request.path_info
request.COOKIES
…… # 返回数据 #########
return HttpResponse # 支持返回字符串 和 bytes类型
return render # 渲染页面
return redirect # 跳转 # 返回cookie ##
response = HttpResponse('ok')
response.set_cookie()
return response
# 把cookie,放到响应头里面,客户端浏览器去响应头里面获取。。所以也能设置响应头内容
response['name'] = 'lgeng'
4、Model操作(原生Sql也可以)
# 表内容操作:
models.TB.objects.create()
obj = models.TB(..)
obj.save()
models.TB.objects.all()[7:10] # 切片
models.TB.objects.update()
models.TB.objects.filter()
models.TB.objects.delete
models.TB.objects.values
models.TB.objects.values_list
models.TB.objects.get
models.TB.objects.filter().update()
models.TB.objects.filter().first()
models.TB.objects.filter(**{}).count()
models.TB.objects.filter(双下划线跨表)
models.TB.objects.filter(id__gte=1)
models.TB.objects.exclude(id__lt=1) models.TB.objects.filter(id_in=[1,2,3]) # id__in # 多对多
obj.set
obj.add([1,2,3])
obj.add(1,2,3)
obj.remove([1,2,3])
obj.clear() models.TB.objects.all()
[obj,obj]
obj.fk.name
models.TB.objects.all().order_by('')
models.TB.objects.distinct() ## 跨表操作 ###########
class A:
name ...
# 而A表操作B表,通过表名+‘_set’ --> b_set
class B:
caption ...
fk = ForignKey(A) # B表操作A表,通过 fk.
5、模板语言
# 基本操作
def func(request):
return render(request,'index.html',{'val':[1,2,3]})
# index.html 里
<h1>{{ val.0 }}</h1>
# 继承
extends "layout.html"
# include
组件
# simpli_tag, filter
转载请务必保留此出处:http://www.cnblogs.com/lgeng/articles/7365891.html
<!-- END -->
《版本说明》: 本文转自 -- http://blog.csdn.net/fgf00/article/details/5429199
Django(六)Session、CSRF、中间件的更多相关文章
- Django之csrf中间件及auth模块使用
目录 一.基于配置文件的编程思想 1. importlib 模块 2. 配置文件 二.跨站请求伪造(csrf) 1.csrf简介以及由来 2.Django中的csrf中间件如何使用 2.1 普通for ...
- django框架进阶-CSRF认证
############################################### """ django中csrf的实现机制 #第一步:django第一次响应 ...
- 30.Django CSRF 中间件
CSRF 1.概述 CSRF(Cross Site Request Forgery)跨站点伪造请求,举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用 ...
- 7.Django CSRF 中间件
CSRF 1.概述 CSRF(Cross Site Request Forgery)跨站点伪造请求,举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用 ...
- django之cookies,session 、中间件及跨站请求伪造
cookies 和session 为什么会有cookie? 由于http协议是无状态的,即用户访问过后,不留痕迹(状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被 ...
- Django之cookie与session、中间件
目录 cookie与session 为什么会有cookie和session cookie 设置cookie 获取cookie 删除cookie 实例:cookie版登录校验 session 设置ses ...
- django csrf 中间件
CSRF和中间件 CSRF使用 说明csrf存在cookie中 全局使用 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', ...
- django模块导入/函数/中间件/MVC和MTV/CSRF
目录 一:模块导入 二:函数 三:中间件 四:MVC和MTV 五:csrf 一:模块导入 第一种:继承 这里的母版更像是一个架子,子板都是定义的内容(如果多个页面中 ,存在相同的页面:这样我们可以抽到 ...
- django—csrf中间件校验流程
CSRF(跨站请求伪造)是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法. 这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求 ...
- Django框架-cookie和session以及中间件
目录 一.cookie 和 session 1.为什么会有这些技术 2. cookie 2.1 Django如何设置cookie 2.2 Django如何获取cookie 2.3 Django如何设置 ...
随机推荐
- TabBottomFragmentLayout【自定义底部选项卡区域(搭配Fragment)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 自定义底部选项卡布局LinearLayout类,然后配合Fragment,实现切换Fragment功能. 缺点: 1.底部选项卡区域 ...
- 基于MongoDB.Driver的扩展
由于MongoDB.Driver中的Find方法也支持表达式写法,结合[通用查询设计思想]这篇文章中的查询思想,个人基于MongoDB扩展了一些常用的方法. 首先我们从常用的查询开始,由于MongoD ...
- Cannot execute request on any known server或DiscoveryClient_UNKNOWN/DESKTOP-MQ8D0C9:8761
报错信息如下: 2018-08-31 11:45:33.619 WARN 1068 --- [freshExecutor-0] c.n.d.s.t.d.RetryableEurekaHttpClien ...
- [Flashback]开启数据库闪回数据库功能
Flashback是Oracle中一个重要的功能,想要使用闪回数据库功能,需要将数据库置于闪回数据库的状态. 1.检查数据库是否开启归档状态 SQL> archive log list; Dat ...
- MySql 创建新用户
grant all privileges on scdb.* to szl@localhost identified by '******'; 说明:1.all privileges 所有可用权限,也 ...
- arcgis api 3.x for js 入门开发系列十五台风轨迹
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- (最完美)MIUI12系统的Usb调试模式在哪里开启的步骤
当我们使用安卓手机通过数据线链接到Pc的时候,或者使用的有些app比如我们公司营销小组当使用的app引号精灵,之前的老版本就需要开启usb调试模式下使用,现当新版本不需要了,如果手机没有开启usb调试 ...
- 业务与IT技术
最近听一个同事又再次提问关于业务比技术重要,是真的吗? 今天我们再来看一下. 一,什么是业务? 业务意指某种有目的的工作或工作项目.技术可以指人类对机器.硬件或人造器皿的运用,但它也可以包含 ...
- 【抱怨文】vscode对多项目支持不够友好
vscode是一个简单的开发工具,启动快,速度快.但是当前1.26版本对多项目支持好像有点问题.命令行有个dotnet sln,但是只能添加新项目,却没有创建解决方案的命令.如果强行添加他会提示没有解 ...
- TestLink-Windows安装教程
TestLink-Windows安装教程 QQ群交流:585499566 一.这篇文章的目的 以后工作中要使用Testlink来管理测试的流程,需要在本地或者Testlink服务器上练习使用,在个人本 ...