• 5-flask-session源码(save_session和open_session)、flask闪现、 flask请求扩展


    1 session源码
    1.1 save_session
    1.2 open_session
    1.3 django session的控制

    2 闪现
    3 请求扩展

    1 session源码

    
    1 app.session_interface 默认是某个类的对象,以后全局对象 session,就是SecureCookieSessionInterface()的对象
    2 请求来了,会执行这个对象的: open_session方法
    3 请求走了,会执行这个对象的:save_session方法
    4 找出上面讲的--》读源码--》
    app.run()---->run_simple(地址, 端口, self可调用对象)--->self 是谁?就是 app
    请求来了,就会执行 self可调用对象()--->app()---->对象加括号---》触发---》类的__call__
    请求来了,就会执行flask类的 __call__--->self.wsgi_app(environ, start_response)
        def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any:
            ctx = self.request_context(environ)
            try:
                try:
                    ctx.push()
                    response = self.full_dispatch_request()
                except Exception as e:
                    error = e
                    response = self.handle_exception(e)
                except:  # noqa: B001
                    error = sys.exc_info()[1]
                    raise
                return response(environ, start_response)
            finally:
                if "werkzeug.debug.preserve_context" in environ:
                    environ["werkzeug.debug.preserve_context"](_cv_app.get())
                    environ["werkzeug.debug.preserve_context"](_cv_request.get())
    
                if error is not None and self.should_ignore_error(error):
                    error = None
    
                ctx.pop(error)
    # 5 ctx.push()--->有如下代码
    if self.session is None: # 请求刚来,是空的
        #session_interface 就是SecureCookieSessionInterface类的对象
        self.session = session_interface.open_session(self.app, self.request)
    
        if self.session is None:
            self.session = session_interface.make_null_session(self.app)
            
    #6  SecureCookieSessionInterface类的open_session
    from flask.sessions import SecureCookieSessionInterface
    open_session步骤:
        1 会去cookie中取出session对应的 三段式的字符串
        2 解密,校验签名---》把这个数据--》放到 session对象中
    save_session步骤:   
        1 从session取出数据
        2 加密,签名---放到cookie中
        3 返回给前端
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    1.1 save_session

    '''
    1 视图函数中,咱们  session[name]=lqz
    2 请求走了,会触发save_session
    3 触发save_session时:
    	把session中的数据,加密签名得到三段字符串
    	放到cookie中,放到了浏览器中
    
    '''
    def save_session(
        self, app: Flask, session: SessionMixin, response: Response
    ) -> None:
        name = self.get_cookie_name(app)
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        httponly = self.get_cookie_httponly(app)
    
        # Add a "Vary: Cookie" header if the session was accessed at all.
        if session.accessed:
            response.vary.add("Cookie")
    
            # If the session is modified to be empty, remove the cookie.
            # If the session is empty, return without setting the cookie.
            if not session:
                if session.modified:
                    response.delete_cookie(
                        name,
                        domain=domain,
                        path=path,
                        secure=secure,
                        samesite=samesite,
                        httponly=httponly,
                    )
                    response.vary.add("Cookie")
    
                    return
    
                if not self.should_set_cookie(app, session):
                    return
    
                expires = self.get_expiration_time(app, session)
                # 加密,签名---放到cookie中
                val = self.get_signing_serializer(app).dumps(dict(session))  # type: ignore
                response.set_cookie(
                    name,
                    val,  # type: ignore
                    expires=expires,
                    httponly=httponly,
                    domain=domain,
                    path=path,
                    secure=secure,
                    samesite=samesite,
                )
                response.vary.add("Cookie")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    1.2 open_session

    '''
    1 请求来了,request中带着cookie(也有可能没有)
    2 根据 session这个key,取出value,如果有,就是 我们当时生成的三段
    3 字典=s.loads(value)  把内容验签,解密出来,转成了字典
    4 把这个字典转到 session对象中
    5 以后视图函数中  session[name] 就能取到当时你放的name
    '''
    
    def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None:
        s = self.get_signing_serializer(app)
        if s is None:
            return None
        # val 就是那三段
        val = request.cookies.get(self.get_cookie_name(app))
        if not val:
            # 如果没有带cookie,造个空session,返回
            return self.session_class()
        max_age = int(app.permanent_session_lifetime.total_seconds())
        try:
            data = s.loads(val, max_age=max_age)
            # 解密,校验签名---》把这个数据--》放到 session对象中
            return self.session_class(data)
        except BadSignature:
            return self.session_class()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    1.3 django session的控制

    from django.contrib.sessions.middleware import SessionMiddleware
    
    
    Django 中的 Session 控制主要涉及到用户会话的管理。会话是指在用户与 web 服务器之间的一段时间内,服务器可以存储关于用户的信息的机制。Django 使用 Session 来存储用户的会话信息。
    
    以下是 Django 中关于 Session 控制的一些建议和常用操作:
    
    1. **启用 Session Middleware:** 确保 `django.contrib.sessions.middleware.SessionMiddleware` 被添加到 `MIDDLEWARE` 配置中。
    2. 这是用于处理 session 的中间件。
    
    3. **配置 Session 引擎:** Django 支持多种 Session 引擎,包括数据库引擎、缓存引擎等。
    4. 在 `settings.py` 文件中,通过设置 `SESSION_ENGINE` 来选择使用的引擎。例如:
        # settings.py
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'
    
    
    5. **Session 的过期时间:** 可以通过 `SESSION_COOKIE_AGE` 设置 Session 的过期时间,以秒为单位。默认是 1209600 秒(2 周)。
        # settings.py
        SESSION_COOKIE_AGE = 1209600  # 2 weeks in seconds
    
    
    6. **Session 的存储位置:** 如果选择使用数据库引擎,可以通过 `SESSION_SAVE_EVERY_REQUEST` 设置是否在每个请求中保存 Session 数据。
        # settings.py
        SESSION_SAVE_EVERY_REQUEST = True
    
    
    7. **Session 的清理:** Django 提供了 `clearsessions` 管理命令,用于清理过期的 Session 数据。
        python manage.py clearsessions
    
    
    8. **Session 的使用:** 在视图中,你可以通过 `request.session` 来访问和设置 Session 数据。
        # views.py
        def set_session(request):
            request.session['username'] = 'john'
            return HttpResponse("Session data set.")
    
        def get_session(request):
            username = request.session.get('username', 'Guest')
            return HttpResponse(f"Hello, {username}.")
    
    
    9. **Session 的删除:** 你可以通过 `del request.session['key']` 或者 `request.session.pop('key', None)` 来删除 Session 中的某个键。
    
    Django 的 Session 控制提供了一种灵活和可定制的方式来管理用户的会话信息,
    可以根据项目的需求进行相应的配置。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    2 闪现

    # flash 翻译过来的
    # 假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
    
    # 以后遇到,在当次请求有数据要存,下次请求还能取出来,就可以使用闪现
    ### 设置闪现
        # 1 普通使用 :通过闪现---》放进去,取一次,就没了
        	# flash(s)  # 放到闪现中了,加密放到了cookie总
        # 2 分类,以分类放入
            flash(s, category='xxx')  
            flash('xxx', category='yyy') 
            
    ### 取闪现
        # 1 普通取,全取出来 从闪现中取出来
        # err = get_flashed_messages()[0]
        # 2 根据分类取
        err = get_flashed_messages(category_filter=['xxx'])[0]
        
        
        
    # 总结:
    	1 设置flash,可以按分类设置
        2 去flash,在当前请求中,可以取出多次,都是在的
        3 一旦有请求取出,再去别的的请求中取,就没了,无论有没有分类,都没了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3 请求扩展

    # django 中中间件,对所有请求拦截
    
    # flask中使用请求扩展实现
    	django                   flask
    	-process_request----》before_request
        -process_response--->after_request
     # 就是django中间件
    	请求头中判断有没有user-agent 做反扒
        响应头中加入 跨域的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    from flask import Flask, session, redirect, request, flash, get_flashed_messages,make_response
    
    app = Flask(__name__)
    app.secret_key = 'asdfasdf'
    app.debug = True
    
    
    @app.before_request
    def before():
        # 做统一处理,处理校验失败,不让他继续往后走了
        '''
        return  None---->继续走下一个请求扩展
        return 新手四件套
        '''
        print('来了')
    
    
    @app.before_request
    def before2():
        # 做统一处理,处理校验失败,不让他继续往后走了
        '''
        return  None---->继续走下一个请求扩展
        return 新手四件套
        '''
        print('来了222')
        # return '不行了'
    
    
    @app.after_request
    def after(response):
        print('走了')
        # return response
        
        return make_response('你看到我了')
    
    
    @app.route('/')
    def home():
        print('home')
        return 'home'
    
    
    @app.route('/order')
    def order():
        return 'order'
    
    
    if __name__ == '__main__':
        app.run()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    C专家编程 第10章 再论指针 10.3 在锯齿状数组上使用指针
    setTimeout和setInterval相互实现
    kubernetes核心组件的运行机制
    项目中的用户鉴权是如何实现的?
    CycGan简单实现后生成图片存在的问题
    FreeSWITCH 1.10.10 简单图形化界面9 - 鼎兴FXO网关SIP中继内网IPPBX落地
    Redis的坑
    HTTP Basic 认证
    高校教务系统登录页面JS分析——巢湖学院
    C++ 快速清空队列
  • 原文地址:https://blog.csdn.net/weixin_44145338/article/details/134466162