zoukankan      html  css  js  c++  java
  • flask之自己的session和三方的flask-session组件

    1.flask对session的处理机制

      1.1、 flask的session处理机制(内置,将session保存到加密的cookie中去实现)
          - 请求来的时候,获取随机字符串,(这些都放在内存)
              存在,到数据库(或者文件,某个地方)中获取个人数据
              不存在,创建,创建对象(随机字符串,{存放用户的数据的容器})
          - 视图:操作内存中的对象(随机字符串,{用户的数据})
          - 响应:内存中的对象(随机字符串,{用户的数据})
              将数据保存到数据库
              随机字符串写在用户的cookie中

      1.2、源码分析、

        a.请求进来执行app的__call__()方法,然后执行wsgi_app()方法 

     1 def wsgi_app(self, environ, start_response):
     2     # 1、在request_context这里,实例化RequestContext()对象,environ是请求的相关所有数据
     3     # 封装了request,session,app等
     4     ctx = self.request_context(environ)
     5 
     6     # 2、执行RequestContext()对象的push
     7     ctx.push()
     8     # push内部创建了app_ctx:AppContext(self)对象,
     9     # push操作之后,session就有值了,请求第一次进来,此时的session=特殊的空字典
    10 
    11     error = None
    12     # try的内部其实是在做视图函数的处理
    13     try:
    14         try:
    15             response = self.full_dispatch_request() # 这里找视图函数并执行
    16         except Exception as e:
    17             error = e
    18             response = self.handle_exception(e) # 当在处理视图的时候出错执行这个函数
    19         except:
    20             error = sys.exc_info()[1]
    21             raise
    22         # 给用户返回信息
    23         return response(environ, start_response)
    24     finally:
    25         if self.should_ignore_error(error):
    26             error = None
    27         # 请求结束:执行RequestContext()对象的auto_pop函数
    28         ctx.auto_pop(error)

        a-1. 执行 ctx.push() 

     1 def push(self):
     2    
     3     # app_ctx是LocalStack类的对象。请求一开始进来,app_ctx为空
     4     app_ctx = _app_ctx_stack.top
     5     if app_ctx is None or app_ctx.app != self.app:
     6         # 第一次进来的时候app没有值,这里是实例化AppContext类对象的操作
     7         # app_ctx.g     相当于字典,可以存放before_request的时候传的值,一次使用
     8         app_ctx = self.app.app_context()
     9         # 执行AppContext类对象的push方法
    10         app_ctx.push()
    11         self._implicit_app_ctx_stack.append(app_ctx)
    12     else:
    13         self._implicit_app_ctx_stack.append(None)
    14 
    15     if hasattr(sys, 'exc_clear'):
    16         sys.exc_clear()
    17 
    18     # _request_ctx_stack就是对LocalStark的对象,执行LocalStark的push
    19     _request_ctx_stack.push(self)
    20 
    21     # 获取session信息,
    22     # 请求一开始进来给session赋值,执行当前app的open_session方法,
    23     # self.session实际就是SecureCookieSession()对象
    24     # 由于session此次的赋值是在ctx的push里面赋值,但是Local类中封装了ctx,所以这里的session被赋值,Local中的session也会变化
    25     self.session = self.app.open_session(self.request)
    26     if self.session is None:
    27         self.session = self.app.make_null_session()

        a-1-1、执行 self.app.open_session(self.request) 

    1 def open_session(self, request):
    2     # self.session_interface = SecureCookieSessionInterface()
    3     # 执行SecureCookieSessionInterface()的open_session方法
    4     return self.session_interface.open_session(self, request)

        a-1-2、执行SecureCookieSessionInterface()的open_session方法

     1 def open_session(self, app, request):
     2     # s获取一个加密规则
     3     s = self.get_signing_serializer(app)
     4     if s is None:
     5         return None
     6 
     7     # 去用户请求的cookie中获取原来返回给用户的随机字符串
     8     # 即key为session的值
     9     val = request.cookies.get(app.session_cookie_name)
    10 
    11     if not val:
    12         # 请求第一次进来的时候val没有值,返回一个特殊的空字典
    13         # session_class = SecureCookieSession
    14         # SecureCookieSession继承了一个继承了字典的类,相当于给session创建了一个特殊的字典
    15         return self.session_class()
    16 
    17     max_age = total_seconds(app.permanent_session_lifetime)
    18 
    19     try:
    20         # 把用户浏览器中的cookie的key为session的值解密成字典(dict)
    21         data = s.loads(val, max_age=max_age)
    22         # 再把这个字典转换成特殊的字典,也放到了Local中的ctx中
    23         return self.session_class(data)
    24 
    25     except BadSignature:
    26         return self.session_class()

        b.在视图函数中执行 session['xxx'] = 123

    1 # session['xxx']=123 ---> 执行LocalProxy()的__setitem__()方法
    2 session = LocalProxy(partial(_lookup_req_object, 'session'))

        b-1.执行LocalProxy()的__setitem__()方法

    1 def __setitem__(self, key, value):
    2     # 1.obj = self._get_current_object():执行偏函数,拿到对应的session对象,即一个特殊的空字典
    3     # 2.obj[key] = value   执行SecureCookieSession类的__setitem__()方法,把数据放到了特殊的空字典中
    4     self._get_current_object()[key] = value

        c.请求离开的时候 wsgi_app()--->full_dispatch_request()--->finalize_request()--->process_response() 

     1 def process_response(self, response):
     2     ctx = _request_ctx_stack.top
     3     bp = ctx.request.blueprint
     4     funcs = ctx._after_request_functions
     5     if bp is not None and bp in self.after_request_funcs:
     6         funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
     7     if None in self.after_request_funcs:
     8         funcs = chain(funcs, reversed(self.after_request_funcs[None]))
     9     for handler in funcs:
    10         response = handler(response)
    11     if not self.session_interface.is_null_session(ctx.session):
    12         # ctx.session就是之前创建的特殊的自典,response就是返回值
    13         self.save_session(ctx.session, response)
    14     return response

        c-1.执行 save_session 

    1 def save_session(self, session, response):
    2     # session_interface = SecureCookieSessionInterface
    3     # 执行SecureCookieSessionInterface()的save_session()
    4     return self.session_interface.save_session(self, session, response)

        c-2.执行SecureCookieSessionInterface()的save_session()

    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
    
        if not session:
            # session没有值
            if session.modified:
                # 只要修改session,modified就变化,session是空的并且修改过,表示删除了session
                # 删除cookie
                response.delete_cookie(app.session_cookie_name,
                                       domain=domain, path=path)
            return
    
        if not self.should_set_cookie(app, session):
            return
    
        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)
    
        # dict(session) ---> 转换成自典
        # get_signing_serializer ---> 序列化
        # val ---> 加密之后的值
        val = self.get_signing_serializer(app).dumps(dict(session))
    
        # 将数据加密之后,写到cookie中,flask中默认把session中的数据写到cookie中
        response.set_cookie(app.session_cookie_name, val,
                            expires=expires, httponly=httponly,
                            domain=domain, path=path, secure=secure)

    2.自定义

    3.flask组件

  • 相关阅读:
    cube.js 基于http 通道的数据实时更新bug 解决
    cube.js 基于http 通道的数据实时更新
    cube.js websocket 实时数据更新说明
    phpspy 进行php 项目性能分析
    使用groovy 下载maven依赖包
    java 几个不错的代码生成工具
    语言性能分析工具总结
    使用rbspy 分析ruby应该性能
    dremio v18.0 软件包可以使用了
    nginx rewrite查询字符串重写问题
  • 原文地址:https://www.cnblogs.com/chitalu/p/8746425.html
Copyright © 2011-2022 走看看