一、Cookie

(一)由来

HTTP协议的无状态特性导致每次的请求都是独立的,即客户端和服务器在某次会话中产生的数据不会被保存,因此产生了Cookie,用来保存客户端的用户状态

(二)什么是Cookie

  1. Cookie具体是指服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些信息,以便服务器通过Cookie提取有用信息从而判断访问者
  2. Cookie最大支持4096字节,保存在客户端,安全性低

(三)Django中操作Cookie

(1)设置Cookie

  1. 普通

    • obj.set_cookie(key,value,...)
    • obj为HttpResponse或render或redirect实例化的对象
  2. 加盐
    • obj.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)
    • obj为HttpResponse或render或redirect实例化的对象
  • 参数

    1. key:键
    2. value:值
    3. max_age:超时时间,以秒为单位,不能给IE设置cookie
    4. expires:超时时间,以秒为单位,可以给IE设置cookie
    5. path:cookie生效的路径,/表示根路径,可以被任何URL页面访问
    6. domain:cookie生效的域名
    7. secure:布尔值,是否为HTTPS传输
    8. httponly:布尔值,只能http协议传输,无法被JavaScript获取
# views.py
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        if username == 'wick' and password == '123':
            next_url = request.GET.get('next')
            obj = redirect('/home/')
            if next_url:
                obj = redirect(next_url)
            obj.set_cookie('whoami', 'wick',max_age=30)
            return obj
    return render(request, 'login.html')

(2)获取Cookie

  1. 获取cookie

    request.COOKIES.get('key')

  2. 获取加盐的cookie值

    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

    • default: 默认值
    • salt: 加密盐
    • max_age: 后台控制过期时间
from functools import wraps
def login_auth(func):
    @wraps(func)
    def inner(request,*args, **kwargs):
        print(request.path_info)
        print(request.get_full_path())
        # 判断当前用户是否登录
        if request.COOKIES.get('whoami'):
            res = func(request,*args, **kwargs)
            return res
        else:
            target_url = request.path_info
            return redirect(f'/login/?next={target_url}')
    return inner

(3)删除Cookie

obj.delete_cookie('key'):删除用户浏览器上之前设置的cookie值

@login_auth
def logout(request):
    obj = redirect('/login/')
    obj.delete_cookie('whoami')
    return obj

二、Session

(一)由来

  1. 解决Cookie的安全性和存储限制问题
  2. 服务器生成并保存在服务器,可以存储超过4096字节的键值对(依赖于Cookie)

(二)Django中操作Session

  1. Django中Session存储在django_session表中,第一次使用时需执行迁移命令
  2. Django中Session失效时间默认是14天
  3. 同一个浏览器生成的session都会保存在django_session表中同一条数据中

(1)设置Session

  • 设置Session时发生的事情:

    1. Django内部调用算法生成随机字符串
    2. 将随机字符串和加密后的数据(以及失效时间)存储到django_session表中
    3. 将随机字符串返回给浏览器,浏览器中以sessionid为键名保存为字典形式
  • 设置Session值

    request.session['k1'] = 123
    request.session.setdefault('k1',123) # 存在则不设置
  • 设置Session和Cooike的超时时间

    request.session.set_expiry(value)
    1. 如果value是个整数,session会在些秒数后失效。
    2. 如果value是个datatime或timedelta,session就会在这个时间后失效。
    3. 如果value是0,用户关闭浏览器session就会失效。
    4. 如果value是None,session会依赖全局session失效策略

(2)获取Session

  • 获取Session时发生的事情:

    1. Django内部会去请求头中获取cookie中的sessionid对应的随机字符串
    2. 将该字符串与django_session表中存储的随机字符串进行比对
    3. 比对成功,会把对应的加密后的数据获取出来,封装到request.session中,否则为空字典
  • 获取Session

    # 1. Session中数据
    request.session['k1']
    request.session.get('k1',None)
    
    # 2. 会话session的key
    request.session.session_key
    
    # 3. 检查会话session的key在数据库中是否存在
    request.session.exists("session_key")
    
    # 4. 所有 键、值、键值对
    request.session.keys()
    request.session.values()
    request.session.items()
    request.session.iterkeys()
    request.session.itervalues()
    request.session.iteritems()

(3)删除Session

  1. del request.session['k1']:删除Session中数据
  2. request.session.delete():删除当前会话的所有Session数据,数据库中也会删除
  3. request.session.flush() :删除当前的会话数据并删除会话的Cookie,数据库中也会删除
  4. request.session.clear_expired():将所有Session失效日期小于当前日期的数据删除,(Django中有自动动删除机制)

三、Django中间件

(一)什么是中间件

  1. 中间件是一个用来处理Django的请求和响应的框架级别的钩子,本质上是一个自定义类
  2. 可以全局范围内在视图函数执行前和施行后做一些额外的操作,比如用户登录校验、用户访问频率校验、用户权限校验
  3. Django中默认有七个中间件
# 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',
]

(二)自定义中间件

  1. 中间件可以定义五个方法
  2. 方法中参数request:必需参数,和视图函数中request一样
  3. 方法中返回值为None时, 继续按照django定义的规则向后继续执行
  4. 方法中返回值为HttpResponse对象时, 则直接将该对象返回给用户
# 在settings.py的MIDDLEWARE配置项中注册上述两个自定义中间件
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',
    'app01.mymiddleware.mymidd.MyMidd1',  # 自定义中间件MD1
    'app01.mymiddleware.mymidd.MyMidd2'  # 自定义中间件MD2
]

(1)process_request

  1. 默认按照自上而下的顺序执行MIDDLEWARE中每一个中间件内部的process_request方法
  2. 返回HttpResponse对象:请求会立刻停止从当前中间件的process_response 方法原路返回
# app01/mymiddleware/mymidd.py

from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):
    def process_request(self, request):
        print("MD1里面的 process_request")

class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

(2) process_response

  1. 在视图函数之后 ,默认按照自下而上的顺序执行每个中间件中的process_response 方法
  2. 必须给方法传入两个形参,request和response
  3. 必须返回response:response是视图函数返回的HttpResponse对象 ,浏览器才能接受HttpResponse对象
# app01/mymiddleware/mymidd.py

from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):
    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

(3) process_view

  1. 执行视图函数之前触发(路由匹配之后)
  2. 返回 HttpResponse对象 : 直接在中间件中掉头,倒叙执行一个个process_response方法,最后返回给浏览器
  3. 该方法有四个参数
    1. request: HttpRequest对象
    2. view_func:Django即将使用的视图函数对象
    3. view_args:将传递给视图的位置参数的列表.
    4. view_kwargs是将传递给视图的关键字参数的字典 (不包括request)
# app01/mymiddleware/mymidd.py
from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):
    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

(4) process_exception

  1. 视图函数出现错误异常自动触发,按照从下往上的顺序执行
  2. 两个参数 request 和 exception ( 视图函数异常产生的Exception对象 )
  3. 返回 HttpResponse对象 : 调用模板和中间件中的process_response方法,并返回给浏览器 (不会再执行process_exception 方法)

(5) process_template_response

  1. 视图函数执行完成后, 视图函数返回的对象有一个render()方法时才会执行,倒序执行
  2. 两个参数 request 和 response ,即必须返回response

(6)中间件执行流程

  1. 请求到达中间件, 先按照正序执行每个中间件的process_request方法 ,执行完后匹配路由
  2. 再顺序执行中间件中的process_view方法 ,执行完后执行视图函数
  3. 如果视图函数中有异常,会倒序执行process_exception
  4. 如果视图函数中返回对象有一个render()方法,会倒序执行process_exception方法
  5. 否则,会倒序执行process_response 方法,将响应发给客户端
  • 方法中有response参数的必须返回response(process_template_response、process_response )
  • 方法中没有response参数的(process_view、process_exception、process_response )
    1. 返回none:正常执行
    2. 返回HttpResponse的:会从当前中间件的response方法依次倒序执行,最终发送给客户端

以上,process_request、process_view默认为顺序,process_exception、process_exception、process_response 默认为倒序

四、Token(扩展)

(一)由来

客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比 ,对数据库和服务器压力大,因此产生了Token

(二)什么是Token

  1. Token是服务端生成的一串字符串
  2. 第一次登录时, 服务器生成一个Token返回给客户端
  3. 再次请求时, 客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码

(三)目的

减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮

(四)使用方式

(1) 设备号/设备mac地址作为Token

  1. 登录时将 设备号/mac地址 作为参数传给服务端
  2. 服务端接受后,用变量Token接收并保存在数据库,并将该Token设置到session中 ,下次请求只需比对变量Token
  • 优点: 只要登录一次以后一直可以使用
  • 缺点: 客户端需要带设备号/mac地址作为参数传递,而且服务器端还需要保存

  • 若服务器的Token超时后,将客户端传递的Token向数据库中查询,同时并赋值给变量Token,如此,Token的超时又重新计时

(2) session值作为Token

  1. 携带用户名和密码登陆
  2. 服务端接受后判断,如果正确, 将本地获取sessionID 作为Token返回给客户端
  • 好处:不用存储数据
  • 缺点:session过期后要重新登录

(五)一些问题和解决方案

  • 问题

    在网络不好或者并发请求时会导致多次重复提交数据

  • 解决方案( 将session和Token套用 )

    1. 可以对session进行加锁
    2. 把token放到session中,当后一个请求到来时,使用session中的token进行比对,当不一致时,即为重复提交,不允许通过

(day58)十、Cookie、Session、Token、Django中间件的更多相关文章

  1. Python 之 Django框架( Cookie和Session、Django中间件、AJAX、Django序列化)

    12.4 Cookie和Session 12.41 cookie Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务 ...

  2. django基础之day10,cookie session token

    https://www.cnblogs.com/Dominic-Ji/p/10886902.html cookie session token

  3. Cookie Session 和Django分页

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

  4. cookie, session, token 是什么 以及相应的安全考量

    Cookie cookie 最常见的是用来保存一些账号信息,比如下图里的 记住账号 就是记录到了cookie里面 cookie 更主要的是针对和server通信的,我们知道http 是无状态的,那如果 ...

  5. Python Web学习笔记之Cookie,Session,Token区别

    一.Cookie,Session,Token简介 # 这三者都解决了HTTP协议无状态的问题 session ID or session token is a piece of data that i ...

  6. cookie session token详解

    cookie session token详解 转自:http://www.cnblogs.com/moyand/ 发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, ...

  7. cookie,session,token介绍

    本文目录 发展史 Cookie Session Token 回到目录 发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档 ...

  8. cookie & session & token compare

    cookie & session & token compare cookie.session.token 区别和优缺点 存储位置 cookie 存在 client 端 session ...

  9. cookie,session,token的定义及区别

    参考了很多文章总结的. 1.cookie(储存在用户本地终端上的数据) 服务器生成,发送给浏览器,浏览器保存,下次请求同一网站再发送给服务器. 2.session(会话) a.代表服务器与浏览器的一次 ...

  10. cookie,session,token的理解

    Get  POST 区别异同点 淘宝token的 理解   过程算法 防止伪造请求  伪造相对难 简单发展史  登录的操作: 哪些人往自己的购物车中放商品,  也就是说我必须把每个人区分开,这就是一个 ...

随机推荐

  1. ProjectServer2010升级到ProjectServer2016,Sharepoint2010升级到Sharepoint2016第一章

    之后还原 Project Server 2010 数据库和包含 Project Web App 网站数据的 SharePoint 内容数据库,您可以运行数据和 Project Web App 网站集升 ...

  2. iOS 中使用 webSocket

    iOS 中使用 webSocket 是服务器和app之间的一种通信方式 webSocket 实现了服务端推机制(主动向客户端发送消息).新的 web 浏览器全都支持 WebSocket,这使得它的使用 ...

  3. Python输出16进制不带0x补零,整数转16进制,字符串转16进制

    Python输出16进制不带0x补零,整数转16进制,字符串转16进制   在开发中,我们偶尔会遇到需要将数据通过控制台打印出来,以检查数据传输的准确性.例如调试服务端刚接到的二进制数据(里面包含很多 ...

  4. LeetCode刷题191127

    数据库: 1179 部门表 Department: +---------------+---------+| Column Name | Type |+---------------+-------- ...

  5. 表空间相关SQL

    --查表空间使用率情况(含临时表空间)SELECT D.TABLESPACE_NAME "Name", D.STATUS "Status", TO_CHAR(N ...

  6. 监控利器-Prometheus安装与部署+实现邮箱报警

    Prometheus(普罗米修斯)监控 环境准备: 三台docker主机(centos7):docker01:172.16.1.30部署服务:Prometheus server,Grafana,Nod ...

  7. Oracle通过SQL语句查看table所引用的对象(View/Function/Procedure/Trigger)

    通过使用user_dependencies进行查看,如下: SELECT * FROM user_dependencies WHERE referenced_name='SFCUSN' --Table ...

  8. javascript es6 Promise 异步同步的写法(史上最简单的教程了)

    1 来个简单的例子 var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.lo ...

  9. Redis入门(一)-Redis简介

    最近几年,Rddis非常的火,受到广大中大型公司,特别是互联网公司的青睐.而作为后端开发,如果你不知道Redis或不会用,没用过,你都不好意思出去找工作.可想而知Redis对于IT行业意义多么重大.对 ...

  10. Redis入门(二)-Redis能够做什么

    引言 在上篇文章中,我们讲述了Redis的基本知识让读者对Redis有了基本的了解.那么这一节我们就来看一下Redis究竟能做什么. 上一节我们提到了Redis可用作数据库,高速缓存和消息队列代理.这 ...