一、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. Ligg.EasyWinApp-100-Ligg.EasyWinForm:一款Winform应用编程框架和UI库介绍

        本项目是一个Winform应用编程框架和UI库.通过这个该框架,不需任何代码,通过XML配置文件,搭建任意复杂的Windows应用界面,以类似Execel公式的方式实现基本的过程控制(赋值.条 ...

  2. 通过U盘在物理机安装CentOS出现Timeout的问题

    错误信息:centos dracut timeout..... 解决方案: 在进入install页面是,按e,启动编辑.要保证Label与U盘的卷标保持一致即可.

  3. day97_11_29

    一.数据存储到mongodb 爬取的数据如果需要存储到mongodb中,要通过item,定义一个存储类.再yield一个类. 数据存储的时候需要进过pipelines,再到setting中配置. fr ...

  4. Eclipse alt+/语法不提示的解决方法

    最近公司电脑上的Eclipse没有了自动提示功能,也不是全部不提示,大多数情况下按下“alt+/”键还会产生提示,但是当我在java项目中邪main方法和syso的时候,“alt+/”则会失效,今天在 ...

  5. java之工厂方法设计模式

    工厂方法模式是设计模式中应用最广泛的模式.在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要.工厂方法模式就是解决这个问题,它通过面向对象的手法,将所要创建的具体对象创建工作延迟到了子 ...

  6. C语言程序设计100例之(24):数制转换

    例24   数制转换 题目描述 请你编一程序实现两种不同进制之间的数据转换. 输入格式 共三行,第一行是一个正整数,表示需要转换的数的进制n(2≤n≤16),第二行是一个n进制数,若n>10则用 ...

  7. kubernetes haproxy+keepalive实现master集群高可用

    前言 master的HA,实际是apiserver的HA.Master的其他组件controller-manager.scheduler都是可以通过etcd做选举(--leader-elect),而A ...

  8. 如何关闭jdk自动更新提示

    缘由 国庆将电脑重装了一下,jdk自然也就重装了,一开机总是提示我更新,索性就将他关掉. 解决办法 右键这个图标,点击属性. 将自动更新取消勾选.

  9. java spring是元编程框架---使用的机制是注解+配置

    java spring是元编程框架---使用的机制是注解+配置

  10. (转)理解滑动平均(exponential moving average)

    转自:理解滑动平均(exponential moving average) 1. 用滑动平均估计局部均值 滑动平均(exponential moving average),或者叫做指数加权平均(exp ...