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. Swoole 源码分析之 TCP Server 模块

    首发原文链接:https://mp.weixin.qq.com/s/KxgxseLEz84wxUPjzSUd3w 大家好,我是码农先森. 今天我们来分析 TCP Server 模块 的实现原理,下面这 ...

  2. C# wpf之控制屏幕显示方向旋转

    using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices ...

  3. Qt一键部署配置(Qt程序打包)

    Qt一键部署配置(Qt程序打包)   1.版本 系统版本:windows10 Qt版本:5.15.2 2.设置可执行程序输出路径 打开.pro文件,输入DESTDIR = $$PWD/../bin,这 ...

  4. windows下vscode连接linux(虚拟机)进行(伪)远程开发

    免责声明 本文乃至本系列是对网络上传播的内容进行整理以梳理流程,且因为篇幅限制会精简内容,适合面向具有计算机类基础知识的人群,本文内容较为笼统,只有大体上的逻辑,具体的细节肯定是官网上写的准而全,望读 ...

  5. OpenCV笔记(7) 轮廓

    1. 查找轮廓 FindContours public static void FindContours(InputOutputArray image, //输入8-bit单通道的图片 out Mat ...

  6. js 实现密码框的查看和隐藏

    大江东去,浪淘尽,千古风流人物.故垒西边,人道是,三国周郎赤壁.乱石穿空,惊涛拍岸,卷起千堆雪.江山如画,一时多少豪杰.遥想公瑾当年,小乔初嫁了,雄姿英发.羽扇纶巾,谈笑间,樯橹灰飞烟灭.故国神游,多 ...

  7. js数组操作——对象数组根据某个相同的字段分组

    先说点废话 最近在实际业务中,需要编写一个方法根据数组中每一个对象的一个相同字段,来将该字段值相等的对象重新编入一个数组,返回一个嵌套的数组对象,特地来做个总结. 当然需要注意的是,在开发过程这种数组 ...

  8. 自定义动画 jquery的结束动画

      <button name="width">改变宽</button>     <button name="height"> ...

  9. vitual box 安装centos7

    vitual box下载地址: https://www.virtualbox.org/wiki/Downloads centos7下载地址: CentOS Linux 选择7-2009,x86-64 ...

  10. 使用Wesky.Net.OpenTools包来快速实现嵌套型结构体数据转换功能

    今天遇到有人提到结构体和byte数组互转的问题,我就顺便拿来水一篇.这是一个冷门的问题,估计使用的人不多.既然有需求,应该就有使用场景,那就顺便整一波. 为了达到效果,结构体.复杂结构体嵌套等都能实现 ...