文章
江湖

大丈夫

thphd  ·  2021年9月4日 2047前站长
内容已隐藏
内容已被作者本人或管理员隐藏。 如有疑问,请点击菜单按钮,查看管理日志以了解原因。
菜单
  1. thphd   2047前站长
    from itsdangerous import Signer
    from base64 import b64encode,b64decode
    
    ...
    
    # rough implementation of JSON Web Signature (JWS)
    def signj(json_object): # object -> utf8str
        json_str = json.dumps(json_object)
        json_bin = json_str.encode('utf-8')
        json_bin_b64 = b64encode(json_bin)
        json_bin_b64_signed_bin = signer.sign(json_bin_b64)
        json_bin_b64_signed_str = json_bin_b64_signed_bin.decode('utf-8')
        return json_bin_b64_signed_str
    
    def unsignj(json_bin_b64_signed_str): # utf8str -> object
        try:
            json_bin_b64_signed_bin = json_bin_b64_signed_str.encode('utf-8')
            json_bin_b64 = signer.unsign(json_bin_b64_signed_bin)
            json_bin = b64decode(json_bin_b64)
            json_str = json_bin.decode('utf-8')
            json_object = json.loads(json_str)
    
            return json_object
        except Exception as e:
            log_err('unsign err', e)
        return {}
    
    def save_session(resp):
        curr_sess_string = get_current_session_str()
        newly_signed_sess_string = signj(g.session)
    
        if newly_signed_sess_string != curr_sess_string:
            qprint('save_session', g.session)
            resp.set_cookie(
                key='session',
                value=newly_signed_sess_string,
                max_age=86400*31,
                httponly=True,
                samesite='strict',
            )
    
    def load_session():
        css = get_current_session_str()
        if css:
            return unsignj(css)
        else:
            return {}
    
    def get_current_session_str():
        return request.cookies.get('session', default='')
    

    caching unsignj() is problematic since dictionaries are mutable.

  2. thphd   2047前站长

    unsignj() takes a cryptographically signed session string and returns a dict in a deterministic fashion. however, if you cache this function and modify the returned dict, later calls to this function with the same arguments will start returning the modified dict, instead of a fresh copy.

    when a user first visits our site, his session string is usually empty. if we pass that empty string to a cached version of unsignj, it will start returning the SAME empty dict whenever the input is an empty string. which means, if you weren't alrealy logged in, you'll share a session object with anyone who also weren't logged in. After person A login into account A (by writing his uid into the dict), everyone who weren't logged in will find themselves using account A.

    solution: return cached_unsignj().copy()

  3. thphd   2047前站长

    modified(current) version:

    def unsignj(json_bin_b64_signed_str):
        return unsignj_cached(json_bin_b64_signed_str).copy()
    
    @lru_cache(maxsize=4096)
    def unsignj_cached(json_bin_b64_signed_str): # utf8str -> object
        json_bin_b64_signed_bin = json_bin_b64_signed_str.encode('utf-8')
        json_bin_b64 = signer.unsign(json_bin_b64_signed_bin)
        json_bin = b64decode(json_bin_b64)
        json_str = json_bin.decode('utf-8')
        json_object = json.loads(json_str)
        return json_object
    
    def load_session():
        css = get_current_session_str()
        if not css: return {}
        try:
            return unsignj(css)
        except Exception as e:
            print_err('unsign err', e)
            return {}
    
  4. 7站女鬼  
    内容已隐藏
    内容已被作者本人或管理员隐藏。 如有疑问,请点击菜单按钮,查看管理日志以了解原因。