session源码、闪现、请求扩展

发布时间 2023-11-17 21:39:24作者: 吼尼尼痛

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 返回给前端
'''

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")

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()

django session的控制

from django.contrib.sessions.middleware import SessionMiddleware

闪现

# 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 一旦有请求取出,再去别的的请求中取,就没了,无论有没有分类,都没了

请求扩展

# django 中中间件,对所有请求拦截

# flask中使用请求扩展实现
    django                   flask
    -process_request----》before_request
    -process_response--->after_request
 # 就是django中间件
    请求头中判断有没有user-agent 做反扒
    响应头中加入 跨域的
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()