⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 session.py

📁 Mod_python is an Apache module that embeds the Python interpreter within the server. With mod_python
💻 PY
📖 第 1 页 / 共 2 页
字号:
 # vim: set sw=4 expandtab : # # Copyright 2004 Apache Software Foundation  #  # Licensed under the Apache License, Version 2.0 (the "License"); you # may not use this file except in compliance with the License.  You # may obtain a copy of the License at # #      http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied.  See the License for the specific language governing # permissions and limitations under the License. # # Originally developed by Gregory Trubetskoy. # # $Id: Session.py 472053 2006-11-07 10:11:01Z grahamd $import apache, Cookieimport _apacheimport osimport statimport timeimport anydbm, whichdbimport randomimport md5import cPickle, cStringIOimport tempfileimport tracebackimport reCOOKIE_NAME="pysid"DFT_TIMEOUT=30*60 # 30 minDFT_LOCK = TrueCLEANUP_CHANCE=1000 # cleanups have 1 in CLEANUP_CHANCE chancetempdir = tempfile.gettempdir()def _init_rnd():    """ initialize random number generators    this is key in multithreaded env, see    python docs for random """    # query max number of threads        if _apache.mpm_query(apache.AP_MPMQ_IS_THREADED):        gennum = _apache.mpm_query(apache.AP_MPMQ_MAX_SPARE_THREADS)    else:        gennum = 10    # make generators    # this bit is from Python lib reference    g = random.Random(time.time())    result = [g]    for i in range(gennum - 1):        laststate = g.getstate()        g = random.Random()        g.setstate(laststate)        g.jumpahead(1000000)        result.append(g)    return resultrnd_gens = _init_rnd()rnd_iter = iter(rnd_gens)def _get_generator():    # get rnd_iter.next(), or start over    # if we reached the end of it    global rnd_iter    try:        return rnd_iter.next()    except StopIteration:        # the small potential for two threads doing this        # seems does not warrant use of a lock        rnd_iter = iter(rnd_gens)        return rnd_iter.next()def _new_sid(req):    # Make a number based on current time, pid, remote ip    # and two random ints, then hash with md5. This should    # be fairly unique and very difficult to guess.    #    # WARNING    # The current implementation of _new_sid returns an    # md5 hexdigest string. To avoid a possible directory traversal    # attack in FileSession the sid is validated using    # the _check_sid() method and the compiled regex    # validate_sid_re. The sid will be accepted only if len(sid) == 32    # and it only contains the characters 0-9 and a-f.     #    # If you change this implementation of _new_sid, make sure to also    # change the validation scheme, as well as the test_Session_illegal_sid()    # unit test in test/test.py.    # /WARNING    t = long(time.time()*10000)    pid = os.getpid()    g = _get_generator()    rnd1 = g.randint(0, 999999999)    rnd2 = g.randint(0, 999999999)    ip = req.connection.remote_ip    return md5.new("%d%d%d%d%s" % (t, pid, rnd1, rnd2, ip)).hexdigest()    validate_sid_re = re.compile('[0-9a-f]{32}$')def _check_sid(sid):    ## Check the validity of the session id    # # The sid must be 32 characters long, and consisting of the characters    # 0-9 and a-f.    #     # The sid may be passed in a cookie from the client and as such    # should not be trusted. This is particularly important in    # FileSession, where the session filename is derived from the sid.    # A sid containing '/' or '.' characters could result in a directory    # traversal attack        return not not validate_sid_re.match(sid)class BaseSession(dict):    def __init__(self, req, sid=None, secret=None, lock=1,                 timeout=0):        self._req, self._sid, self._secret = req, sid, secret        self._lock = lock        self._new = 1        self._created = 0        self._accessed = 0        self._timeout = 0        self._locked = 0        self._invalid = 0                dict.__init__(self)        config = req.get_options()        if config.has_key("mod_python.session.cookie_name"):            session_cookie_name = config.get("mod_python.session.cookie_name", COOKIE_NAME)        else:            # For backwards compatability with versions            # of mod_python prior to 3.3.            session_cookie_name = config.get("session_cookie_name", COOKIE_NAME)        if not self._sid:            # check to see if cookie exists            if secret:                  cookie = Cookie.get_cookie(req, session_cookie_name,                                           Class=Cookie.SignedCookie,                                           secret=self._secret,                                           mismatch=Cookie.Cookie.IGNORE)            else:                cookie = Cookie.get_cookie(req, session_cookie_name)            if cookie:                self._sid = cookie.value        if self._sid:            if not _check_sid(self._sid):                if sid:                    # Supplied explicitly by user of the class,                    # raise an exception and make the user code                    # deal with it.                    raise ValueError("Invalid Session ID: sid=%s" % sid)                else:                    # Derived from the cookie sent by browser,                    # wipe it out so it gets replaced with a                    # correct value.                    self._sid = None        self.init_lock()        if self._sid:            # attempt to load ourselves            self.lock()            if self.load():                self._new = 0        if self._new:            # make a new session            if self._sid: self.unlock() # unlock old sid            self._sid = _new_sid(self._req)            self.lock()                 # lock new sid            Cookie.add_cookie(self._req, self.make_cookie())            self._created = time.time()            if timeout:                self._timeout = timeout            else:                self._timeout = DFT_TIMEOUT        self._accessed = time.time()        # need cleanup?        if random.randint(1, CLEANUP_CHANCE) == 1:            self.cleanup()    def make_cookie(self):        config = self._req.get_options()        if config.has_key("mod_python.session.cookie_name"):            session_cookie_name = config.get("mod_python.session.cookie_name", COOKIE_NAME)        else:            # For backwards compatability with versions            # of mod_python prior to 3.3.            session_cookie_name = config.get("session_cookie_name", COOKIE_NAME)        if self._secret:            c = Cookie.SignedCookie(session_cookie_name, self._sid,                                    secret=self._secret)        else:            c = Cookie.Cookie(session_cookie_name, self._sid)        if config.has_key("mod_python.session.application_domain"):             c.domain = config["mod_python.session.application_domain"]         if config.has_key("mod_python.session.application_path"):            c.path = config["mod_python.session.application_path"]        elif config.has_key("ApplicationPath"):            # For backwards compatability with versions            # of mod_python prior to 3.3.            c.path = config["ApplicationPath"]        else:            # the path where *Handler directive was specified            dirpath = self._req.hlist.directory             if dirpath:                docroot = self._req.document_root()                c.path = dirpath[len(docroot):]            else:                c.path = '/'            # Sometimes there is no path, e.g. when Location            # is used. When Alias or UserDir are used, then            # the path wouldn't match the URI. In those cases            # just default to '/'            if not c.path or not self._req.uri.startswith(c.path):                c.path = '/'        return c    def invalidate(self):        c = self.make_cookie()        c.expires = 0        Cookie.add_cookie(self._req, c)        self.delete()        self._invalid = 1    def load(self):        dict = self.do_load()        if dict == None:            return 0        if (time.time() - dict["_accessed"]) > dict["_timeout"]:            return 0        self._created  = dict["_created"]        self._accessed = dict["_accessed"]        self._timeout  = dict["_timeout"]        self.update(dict["_data"])        return 1    def save(self):        if not self._invalid:            dict = {"_data"    : self.copy(),                     "_created" : self._created,                     "_accessed": self._accessed,                     "_timeout" : self._timeout}            self.do_save(dict)    def delete(self):        self.do_delete()        self.clear()    def init_lock(self):        pass                def lock(self):        if self._lock:            _apache._global_lock(self._req.server, self._sid)            self._locked = 1            self._req.register_cleanup(unlock_session_cleanup, self)    def unlock(self):        if self._lock and self._locked:            _apache._global_unlock(self._req.server, self._sid)            self._locked = 0                def is_new(self):        return not not self._new    def id(self):        return self._sid    def created(self):        return self._created    def last_accessed(self):        return self._accessed    def timeout(self):        return self._timeout    def set_timeout(self, secs):        self._timeout = secs    def cleanup(self):        self.do_cleanup()    def __del__(self):        self.unlock()def unlock_session_cleanup(sess):    sess.unlock()############################################################################# DbmSessiondef dbm_cleanup(data):    dbm, server = data    _apache._global_lock(server, None, 0)    db = anydbm.open(dbm, 'c')    try:        old = []        s = db.first()        while 1:            key, val = s            dict = cPickle.loads(val)            try:                if (time.time() - dict["_accessed"]) > dict["_timeout"]:                    old.append(key)            except KeyError:                old.append(key)            try:                s = db.next()            except KeyError: break        for key in old:            try:                del db[key]            except: pass    finally:        db.close()        _apache._global_unlock(server, None, 0)class DbmSession(BaseSession):    def __init__(self, req, dbm=None, sid=0, secret=None, dbmtype=anydbm,                 timeout=0, lock=1):        if not dbm:            opts = req.get_options()            if opts.has_key("mod_python.dbm_session.database_filename"):                dbm = opts["mod_python.dbm_session.database_filename"]            elif opts.has_key("session_dbm"):                # For backwards compatability with versions                # of mod_python prior to 3.3.                dbm = opts["session_dbm"]            elif opts.has_key("mod_python.dbm_session.database_directory"):                dbm = os.path.join(opts.get('mod_python.dbm_session.database_directory', tempdir), 'mp_sess.dbm')            elif opts.has_key("mod_python.session.database_directory"):                dbm = os.path.join(opts.get('mod_python.session.database_directory', tempdir), 'mp_sess.dbm')            else:                # For backwards compatability with versions                # of mod_python prior to 3.3.                dbm = os.path.join(opts.get('session_directory', tempdir), 'mp_sess.dbm')        self._dbmfile = dbm        self._dbmtype = dbmtype        BaseSession.__init__(self, req, sid=sid, secret=secret,                             timeout=timeout, lock=lock)    def _set_dbm_type(self):        module = whichdb.whichdb(self._dbmfile)        if module:            self._dbmtype = __import__(module)            def _get_dbm(self):        result = self._dbmtype.open(self._dbmfile, 'c', stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)        if self._dbmtype is anydbm:            self._set_dbm_type()        return result    def do_cleanup(self):        data = [self._dbmfile, self._req.server]        self._req.register_cleanup(dbm_cleanup, data)        self._req.log_error("DbmSession: registered database cleanup.",                            apache.APLOG_NOTICE)    def do_load(self):        _apache._global_lock(self._req.server, None, 0)        dbm = self._get_dbm()        try:            if dbm.has_key(self._sid):                return cPickle.loads(dbm[self._sid])            else:                return None        finally:            dbm.close()            _apache._global_unlock(self._req.server, None, 0)    def do_save(self, dict):        _apache._global_lock(self._req.server, None, 0)        dbm = self._get_dbm()        try:            dbm[self._sid] = cPickle.dumps(dict)        finally:            dbm.close()            _apache._global_unlock(self._req.server, None, 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -