一、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. vue项目在git commit时,使用eslint检测

    用vue-cli3创建新项目可以自定义配置,选择eslint,所以eslint不需要配置, 项目根目录下面生成一个 .eslintrc.js文件,里面可以自定义配置eslint规则 现在在开发的时候, ...

  2. HIFIMAN TWS600A听感小记——测评出街Man

    HIFIMAN TWS600A听感小记——测评出街Man 几年前蓝牙耳塞在大哥苹果的带领下有着掀翻小池塘的气势.蓝牙耳塞完全替代了我在通勤路上用的有线塞子,当时随便买了一副两百多元的塞子,低音轰头就算 ...

  3. ssdb make 失败 autoconf required

    ERROR! autoconf required! install autoconf first Makefile:4: build_config.mk: No such file or direct ...

  4. 初学Elasticsearch

    首先启动elasticsearch.bat,然后安装node.js为了支持elasticsearch-head-master插件,之后在在该插件的目录打开命令行窗口,输入grunt server即可S ...

  5. make:yacc/lex:command not be found

    1.使用./build编译boa-0.94.13时出现make:yacc:command not be found 解决方法:apt-get install -y byacc 2.出现make:lex ...

  6. 关于soapui接口的笔记

    1.接口包含内容 #request: HTTP版本/请求地址url 请求方法:GET.POST.PUT.DELETE等 请求头:content—type 请求正文:请求参数 #response: 状态 ...

  7. Flink| 运行架构

    1. Flink运行时组件 作业管理器(JobManager) 任务管理器(TaskManager) 资源管理器(ResourceManager) 分发器(Dispatcher) 2. 任务提交流程 ...

  8. SpringData JPA实现增删改

    一.创建实体类并自动生成数据库表 二.dao层继承JpaRepository 三.controller中增加操作 四.controller中删除操作 五.controller中修改操作

  9. angularjs路由监听,uirouter感知路由变化,解决uirouter路由监听不生效的问题

     壹 ❀ 引 angularjs除了惊为天人的双向数据绑定外,路由也是出彩的一笔,通过路由配置,我们能在不发起页面跳转的情况下,对当前页内容进行整体更新,angularjs提供了ngRoute模块用于 ...

  10. HBase删除数据的原理

    转自:https://blog.csdn.net/cenjianteng/article/details/96645447 -------------------------------------- ...