Django 处理http请求之使用session

by:授客 QQ1033553122 欢迎加入全国软件测试交流群:7156436

测试环境

Win7

Django 1.11

 

Django提供了匿名会话支持。允许用户存储和检索任意数据。它在服务端存储数据,并对cookie的发送和接收做了抽象。Cookie包含了一个会话ID--并非数据本身(除非使用cookie based backend)

开启会话

会话是通过中间件实现的。要开启会话功能,需要编辑settings.py文件,编辑MIDDLEWARE变量,确保变量包含 'django.contrib.sessions.middleware.SessionMiddleware'.通过django-admin startproject创建的默认settings.py已经开启了SessionMiddleware

如果不想使用会话,需要从MIDDLEWARE变量中移除SessionMiddleware,并且移除INSTALLED_APPS中的django.contrib.sessions

配置会话引擎

默认的,Django在数据库中存储会话(使用django.contrib.sessions.models.Session model)。虽然很方便,但是在某些情况下,存储会话到别的地方会更快,所以,Django 可以配置为存储会话数据到你的文件系统上,或者是缓存中。

Using database-backed sessions

必须添加'django.contrib.sessions'到settings.py中的INSTALLED_APPS配置

Using cached sessions

Using file-based sessions

Using cookie-based sessions

views视图中使用会话

当开启会话功能,传递给每个Django view视图函数的第一个参数,都会携带一个会话属性--一个类似字典的对象

任何时候,都可以对request.session进行读写,可以多次编辑。

class backends.base.SessionBase

所有会话对象的基类,拥有以下标准字典方法:

__getitem__(key)

例子: fav_color = request.session['fav_color']

 

__setitem__(keyvalue)

例子: request.session['fav_color'] = 'blue'

 

__delitem__(key)

例子: del request.session['fav_color']. 如果给定key不存在会话中,会抛出KeyError。

 

__contains__(key)

例子: 'fav_color' in request.session

 

get(keydefault=None)

根据session_key获取值,如果key不存在则返回default参数指定的值。

例子: fav_color = request.session.get('fav_color', 'red')

 

pop(keydefault=__not_given)

例子: fav_color = request.session.pop('fav_color', 'blue')

 

keys()

获取session_key,类型<class 'dict_keys'>

items()

#setdefault()

setdefault(session_key, value)

如果会话字典的键session_key不存在,则设置session_key的值为value,如果session_key已经存在则不做任何操作

clear()

flush()

从会话中删除当前会话数据和会话cookie。在无法再次通过用户浏览器访问之前的会话数据时这很有用。(比如调用django.contrib.auth.logout()函数将会调用它)。

set_test_cookie()

设置测试cookie来判断用户浏览器是否支持cookie。出于cookie的工作方式考虑,仅在用户发起下一次页面请求时才可以进行判断。

test_cookie_worked()

根据用户浏览器是否接受test cookie返回True、False。出于cookie的工作方式考虑,必须在前一个独立页面请求中才可以调用set_test_cookie()。查看 Setting test cookies获取更多信息。

delete_test_cookie()

删除测试cookie

 

set_expiry(value)

为session设置过期时间。

  • 如果value为整数,无活动超过那个数,会话将过期。例如,request.session.set_expiry(300) 将设定会话过期时间为5分钟。
  • 如果 value 为一个datetime timedelta对象,那么会话将在指定的日期/时间过期。注意,datetimetimedelta值仅在使用PickleSerializer时可序列化。 
  • 如果value0,当用户关闭浏览器会话cookie将会过期。
  • 如果valueNone,将使用全局会话过期策略

读取会话并不会改变会话的活动状态。会话过期时间是从会话上一次被修改的时间算起的。

 

get_expiry_age()

获取会话过期时间。对于那些没有定义过期时间,或者设置为浏览器关闭后才过期的会话,将返回SESSION_COOKIE_AGE

该函数接受两个可选关键词参数:

modification: 表示会话最后修改时间的datetime对象,默认为当前时间。

expiry: 会话过期信息,一个datetime对象、或者是一个int(秒为单位)、或者None。默认为set_expiry()函数存储在会话中的值,如果有的话,否则为None。

get_expiry_date()

返回会话过期日期。对于那些没有定义过期时间,或者设置为浏览器关闭后才过期的会话,等同于从现在开始算起,加上SESSION_COOKIE_AGE秒后的日期。(For sessions with no custom expiration (or those set to expire at browser close), this will equal the date SESSION_COOKIE_AGE seconds from now)

该函数同get_expiry_age()一样,接受统一的关键词参数。

get_expire_at_browser_close()

根据用户关闭浏览器用户会话是否过期返回True、False。

clear_expired()

从会话存储中移除过期会话。该类方法被 clearsessions调用。

cycle_key()

保留当前会话数据时创建一个新的会话key。django.contrib.auth.login()会调用该方法

例子

 

#-*- encoding:utf-8 -*-

 

 

__author__ = 'shouke'

 

from django.shortcuts import render

# Create your views here.

from django.template.response import TemplateResponse

# 可以把request.session当字典使用

def test_view(request):

print(request.session.keys())# 输出键,数据类型:dict_keys

print(request.session.values())# 输出值, 数据类型:dict_values

print(request.session.items())# 输出键值对, 数据类型:dict_items

username = request.session.get('username', 'unknow') #获取键对应的值,如果键不存在则返回unknow

print('username: %s ' % username)

username = request.session.get('myusername', 'unknow')

print('myusername: %s ' % username)# 输出myusername: unknow

# request.session.setdefault(session_key, value)

# 设置session_key的默认值为value,如果session_key已存在则不设置

request.session.setdefault('myusername', 'shouke')

request.session.setdefault('myusername', 'shouke2')

username = request.session.get('myusername')

print('myusername: %s ' % username)# 输出myusername: shouke

request.session['myusername'] = 'keshou'# 设置键的值

username = request.session['myusername']

print('myusername: %s ' % username)# 输出myusername: keshou

# 删除键值对

username = request.session.pop('myusername')

print('myusername: %s ' % username)

# 等价实现

# delrequest.session['myusername']

print(request.session.session_key)# 会话ID,# 即SESSION_COOKIE_NAME,存放在数据表.字段:django_session.session_key

print(request.session.exists(request.session.session_key))# 判断会话ID是否存在

request.session.clear_expired()# 删除过期会话(过期时间小于当前时间的会话)

request.session.delete(request.session.session_key)# 删除指定会话

 

request.session.clear() # 清除所有会话数据

# request.session.flush() # 清除所有会话数据并删除会话cookie

print(request.session.keys()) # 输出[]

 

return render(request, 'website/pages/mytest.html',{})

注意:使用request.session.get('username') 比使用#request.session['username']安全,前者如果不存在名为username的字典key,则返回None,后者则会报错。

会话序列化

默认的Django使用JSON序列化session数据。可以使用SESSION_SERIALIZER 配置自定义会话序列化格式。强烈推荐使用JSON序列化,特别是使用backend cookie的情况下(存在安全问题)。

Bundled serializers

class serializers.JSONSerializer

注意:保存字典类型的内容到会话中,django会对被保存的字典内容执行序列化,这会导致字典中的键值对失去原有的顺序解决方案

所以得先采用json.dumps把内容转为字符串,再次从会话中取出该字符串时,使用json.loads转字符串为字典,这样可以保持字典内容的顺序不变

其它,略

class serializers.PickleSerializer

支持任意python对象,但是存在安全问题。略

Write your own serializer

会话对象指南

  • 使用普通python字符串作为request.session字典的key。这更是一种约定,而非硬性规则.
  • 下划线开头的会话字典key保留为Django内部使用.
  • 不要使用新的对象覆盖request.session,并且不要访问、设置其属性。像字典一样使用它。

例子

用户提交一个评论后设置has_commented为True,即限制用户只提交一次:

def post_comment(request, new_comment):

if request.session.get('has_commented', False):

return HttpResponse("You've already commented.")

c = comments.Comment(comment=new_comment)

c.save()

request.session['has_commented'] = True

return HttpResponse('Thanks for your comment!')

设置测试cookies

典型用法:

from django.http import HttpResponse
from django.shortcuts import render
 
def login(request):
if request.method=='POST':
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse("You're logged in.")
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
return render(request,'foo/login_form.html')

注意:实践验证,要按以下形式写才可以

request.session.set_test_cookie()

if request.session.test_cookie_worked():

request.session.delete_test_cookie()

else:

# do something

view视图之外使用会话

注意:

以下例子,直接从django.contrib.sessions.backends.db引入SessionStore 对象,实际编码中需要结合实际,从SESSION_ENGINE设置的对应会话引擎中引入 SessionStore:

>>> from importlib import import_module
>>> from django.conf import settings
>>> SessionStore=import_module(settings.SESSION_ENGINE).SessionStore

提供了在视图之外维护session数据的api

>>> from django.contrib.sessions.backends.db import SessionStore
>>> s=SessionStore()
>>> # 由于datetime不支持按JSON格式序列化,所以存储为对应的秒数
>>> s['last_login']=1376587691
>>> s.create()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
>>> s=SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login']
1376587691

SessionStore.create() 用于创建一个新的会话(比如,一个不是从会话存储中加载并且携带session_key=None的会话)。 save() 用于保存一个已有会话(比如,一个从会话存储中加载的会话)。对一个新会话执行save()调用,也可起作用,生成一个和已存在session_key冲突的session_key的机率更小。 create() 调用save()方法,假如生成的session_key已经存在,会循环调用直到生成一个未使用session_key.

如果当前使用的是django.contrib.sessions.backends.db 每个会话都是一个普通的Django model实例。Sessionmodel定义在django/contrib/sessions/models.py,因为它是一个普通的model,所以可以通过普通的Django数据库api访问会话:

>>>from django.contrib.sessions.models import Session
>>>s=Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>>s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)

注意,必须调用 get_decoded() 来获取session字典,因为session字典是按一定格式编码后存储的。

>>>s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>>s.get_decoded()
{'user_id': 42}

何时存储会话

默认的,Django仅在会话被修改后存储到会话数据库--也就是说,只要任意会话字典值被赋值或者删除:

#修改会话
request.session['foo']='bar'
del request.session['foo']
request.session['foo']={}
 
# 会话未被修改,因为它更改的是request.session['foo'],而非request.session.
request.session['foo']['bar']='baz'

上述最后一种情况下,如果我们想显示的告诉django会话已经被修改,需要增加以下语句:

request.session.modified=True

如果想要改变这种默认行为,可以设置SESSION_SAVE_EVERY_REQUEST 配置为True。这样以后,Django将会针对每个请求存储会话到数据库。

注意,默认的,会话cookie仅在会话被修改、创建时才会发送给客户端。如果SESSION_SAVE_EVERY_REQUEST被设置True,针对每个请求,都会发送会话cookie

类似的,每次发送会话cookie,都会更新会话cookie组成部分expires

如果响应状态码为500,不会保存会话。

Browser-length sessions vs. persistent sessions

可以通过修改SESSION_EXPIRE_AT_BROWSER_CLOSE配置,控制会话框架使用browser-length sessions 还是 persistent sessions 。

默认的,SESSION_EXPIRE_AT_BROWSER_CLOSE被设置为False,也就是说会话cookie会存储在用户浏览器中,存储时长和SESSION_COOKIE_AGE一样久。这样就重新打开浏览器不需要重新登录

如果SESSION_EXPIRE_AT_BROWSER_CLOSE被设置为TrueDjango将使用browser-length cookies – 用户一关闭浏览器,cookie就失效。这样,每次重新打开浏览器,用户都要重新登录。

该配置是全局配置的,可以通过调用 request.sessionset_expiry()的方法对单个视图中的会话进行配置。

注意:一些浏览器,比如chrome,提供允许用户关闭浏览器,重新打开浏览器后用户可以不用重新登录继续会话操作。这会影响SESSION_EXPIRE_AT_BROWSER_CLOSE配置

 

清除会话存储

会话后端当使用数据库时,用户登录时,Django会添加一行记录到django_session数据表,每次会话被修改时,Django会更新对应记录,如果用户手动退出,Django会删除该行数据,但是如果用户一直不退出,该行记录不会被删除。会话后端使用文件时也是类似这个处理过程。

Django 不提供过期会话自动清理,所以,需要自己定期清理过期会话。出于这个目的,Django 提供了一个清理管理命令: clearsessions. 推荐定期执行这个命令

注意,假如会话后端使用缓存,则不存这个问题,因为缓存会自动清理过期数据。

Settings.py中的配置

设置session cookie失效日期(默认值:2周,1209600毫秒)

SESSION_COOKIE_AGE = 1209600                             #默认

设置session cookie的域名,例子:

SESSION_COOKIE_DOMAIN = None            # 默认

设置session cookie是否只支持http传输,例子:

SESSION_COOKIE_HTTPONLY = True                           # 默认

设置session cookie名称,即session的cookie保存在浏览器上时的key,例子:

SESSION_COOKIE_NAME = 'sessionid' #默认

设置session cookie路径,例子:

session_cookie_name = '/'  # 默认

设置是否Https传输cookie,例子:

SESSION_COOKIE_SECURE = False    # 默认

配置会话引擎,例子:

SESSION_ENGINE = 'django.contrib.sessions.backends.db'   #默认

设置是否关闭浏器session立即过期

SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  #默认

设置是否每次请求都保存session,例子:

SESSION_SAVE_EVERY_REQUEST = False                       #默认

会话安全

  • 尽量使用JSONSerializer,而不是PickleSerializer
  • 存储会话数据到django_session数据表。
  • 仅在需要时发送cookie

SessionStore 对象

当在内部处理会话时,Django使用来自相应会话引擎的会话存储对象。按约定,会话存储对象类名为SessionStore,并且位于SESSION_ENGINE指定的模块中。

Django中可获取的SessionStore对象继承与SessionBase ,并实现了以下数据维护方法:

Extending database-backed session engines

Session IDs in URLs

参考链接

https://docs.djangoproject.com/en/dev/topics/http/sessions/

Django 处理http请求之使用session的更多相关文章

  1. python运维开发(十九)----Django后台表单验证、session、cookie、model操作

    内容目录: Django后台表单验证 CSRF加密传输 session.cookie model数据库操作 Django后台Form表单验证 Django中Form一般有2种功能: 1.用于做用户提交 ...

  2. Django跨域、cookie、session

    前后台分离开发 1.前台页面运行在前台服务器上,负责页面的渲染(静态文件的加载)与跳转 2.后台代码运行在后台服务器上,负责数据的处理(提供数据请求的接口) 跨域 什么是跨域? 通常情况下,A网页访问 ...

  3. Django框架详细介绍---cookie、session、自定义分页

    1.cookie 在HTTP协议介绍中提到,该协议是无状态的,也就是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的 ...

  4. Django(十)COOKIE和session

    https://www.cnblogs.com/haiyan123/p/7763169.html from django.shortcuts import render,redirect # Crea ...

  5. {Django基础八之cookie和session}一 会话跟踪 二 cookie 三 django中操作cookie 四 session 五 django中操作session

    Django基础八之cookie和session 本节目录 一 会话跟踪 二 cookie 三 django中操作cookie 四 session 五 django中操作session 六 xxx 七 ...

  6. Django框架介绍之cookie与session

    cookie http请求时无状态的,一个客户端第一次,第二次,第n次访问同一个服务器都是一样的,服务器都会按照一个新的连接处理.但是,有时候客户端需要服务器记住客户端的登录状态,譬如离开一会,回来之 ...

  7. Django基础八之cookie和session

    一 会话跟踪 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而10086服务人员就是服务器 ...

  8. Django学习笔记之Cookie、Session和自定义分页

    cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...

  9. Python自动化运维 - Django(三)CSRF - Cookie&Session

    CSRF跨站请求伪造 CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:攻击者盗用了你的身份,以你的名义发送恶意请求 ...

  10. Django 进阶篇之 CSRF,COOIKE,SESSION

    1.CSRF(Cross Site Request Forgery, 跨站域请求伪造) CSRF 背景与介绍 CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网 ...

随机推荐

  1. 到今天了你还不会集合的Stream操作吗?你要out了

    Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式.Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找.过滤.筛选等操作 ...

  2. python利用flux基本读写influxDB

    1.读取 QuerApi 形式 python 利用 flux 语句查询 influxdb 数据. https://influxdb-client.readthedocs.io/en/latest/ap ...

  3. Dockerfile PHP镜像制作

    1 PHP镜像制作: 1.1 php-dockerfile FROM centos:7 LABEL maintainer www.chenleilei.net RUN yum install -y c ...

  4. TIM_Cmd()函数引发的思考

    在使用定时器的输入捕获进行频率测量时发现用TIM_Cmd()函数关闭定时器后,输入捕获中断还是会被触发,这就很奇怪了,输入捕获是定时器的一种模式,关闭定时器不就意味着输入捕获捕获也被关闭了吗?可是实际 ...

  5. C语言常用数学函数

    目录 C语言常用数学函数(头文件#include "math.h") abs()函数 labs()函数 fabs()函数 floor()函数 floorf() floorl() c ...

  6. react props进阶 children属性

    children属性,表示组件标签的子节点,当组件标签有子节点时,props就会有该属性,与与普通的props一样,其值可以使任意类型. # 父组件 class App extends React.C ...

  7. 算法学习笔记(45): 快速沃尔什变换 FWT

    遗憾的是 math 里面一直没有很好的讲这个东西--所以这次细致说说. FWT 的本质 类似于多项式卷积中,利用 ntt 变换使得卷积 \(\to\) 点乘,fwt 也是类似的应用. 定义某种位运算 ...

  8. OOP第一阶段题集总结

    一.前言 知识点:数组,字符串的使用,链表,hashmap,泛型的使用,正则表达式的使用,类的设计,类与类之间的关系,单一职责. 题量:题目数量为5+4+3,数量适中,其中都是前几题较简单,最后一题较 ...

  9. 喜讯!INFINI Easysearch 在墨天轮搜索型数据库排名中荣登榜首

    近日,2023 年 9 月的 墨天轮中国数据库流行度排行 火热出炉,本月共有 287 个数据库参与排名,中国数据库行业竞争日益激烈.其中,极限科技旗下软件产品 INFINI Easysearch 在 ...

  10. C#.NET ASP.NET IIS 加载.pfx私钥证书时报错“出现了内部错误。”

    C#.NET ASP.NET IIS 加载.pfx私钥证书时报错"出现了内部错误." 原始代码报错: X509Certificate2 x509cer = new X509Cert ...