Parse the implementation code supported by the session in Python's tornado framework

Source: Internet
Author: User
Tags session id
Tornado there's no session inside? No, of course there is ~ I know there must be someone on GitHub to help me write it ~ O (∩_∩) o~
Thus, find the following project, using memcached to achieve the tornado session. The light will not be able to use, let us see how it is written ~

Project Address: Tornado-memcached-sessions

Let's start by looking at the demo ....

In app.py:
First notice that a new application class is defined, which inherits from Tornado.web.Application, where the application parameter settings is set in the initialization method of the class, and then the parent class and Session_ are initialized. Manager. (What is this?) For the moment, whatever it is ... )


Class Application (tornado.web.Application): def __init__ (self): settings = Dict (# set Cookie_secret, for secure _cookie Cookie_secret = "e446976943b4e8442f099fed1f3fea28462d5832f483a0ed9a3d5d3859f==78d", # set Session_secre T used to generate session_id Session_secret = "3CDCB1F00803B6E78AB50B466A40B9977DB396840C28307F428B25E2277F1BCC", # MEMCA Ched address memcached_address = ["127.0.0.1:11211"], # session Expiration Time Session_timeout =, Template_pat h = Os.path.join (Os.path.dirname (__file__), "Templates"), Static_path = Os.path.join (Os.path.dirname (__file__), "STA Tic "), xsrf_cookies = True, Login_url ="/login ",) handlers = [(R"/", MainHandler), (R" /login ", Loginhandler)] # initializes the parent class Tornado.web.Application tornado.web.application.__init__ (self, handlers, **s ettings) # Initializes the class of Session_manager Self.session_manager = session. SessionManager (settings["Session_secret"], settings["memcached_address"], settings["Session_timeout"])  

In the following Loginhandler we can see the use of the session:

Class Loginhandler (Basehandler):   def get (self):     self.render ("login.html")    def post (self):     # Access     self.session["user_name"] = self.get_argument ("name") in the form of a dictionary key-value pair     # Modify the save to invoke the session, otherwise it will be equal to no modification oh ...     Self.session.save ()     

Is it very concise and clear from the point of view? So, careful you are not found now handler not inherit from Tornado.web.RequestHandler? With a strong Zuo (SI) Spirit we opened the base.py. Oh, my God, it's so short. (Oh, where do you want to go ...) )
The Basehandler method is simply initialized and overrides the Get_current_user method for user login verification.

Class Basehandler (Tornado.web.RequestHandler):   def __init__ (self, *ARGC, **argkw):     super (Basehandler, self) . __init__ (*ARGC, **argkw)     # Defines the session of the handler, noting that each access initializes a session instance according to the HTTP feature Oh, it's important     to understand what's behind you. Self.session = Session. Session (Self.application.session_manager, self)    # What's this for? Used to verify login ... Please google about tornado.web.authenticated, is actually tornado provides user authentication   def get_current_user (self):     

See here, is not contented? Oh, I finally understand! Hey, what's The Zuo (SI) spirit? The key is session.py Ah! You have a blank face back to the head ....

First look at the libraries you need:
Pickle a library for serialization deserialization (not understood?) You can just as well act like JSON. )
HMAC and Hashlib used to generate an encrypted string
UUID is used to generate a unique ID
Memcache Python's Memcache client

There are three classes in this, Sessiondata Session and SessionManager. Let's look at the simplest sessiondata.
Sessiondata is used to store session data in a dictionary structure, inheriting from a dictionary, in fact, only two more member variables than the dictionary:

# Inherit the dictionary because the session access is similar to the dictionary class Sessiondata (dict):   # Initializes with session ID and Hmac_key   def __init__ (self, session_id, Hmac_key):     self.session_id = session_id     


Then there is the real Session class. The session class inherits from the Sessiondata, noting that it is still much like a built-in type dictionary, just rewriting its own initialization method and defining the Save interface--to save the modified session data.

# Inherit Sessiondata class Session (sessiondata):   # Initialize, bind Session_manager and tornado corresponding handler   def __init__ (self, S Ession_manager, request_handler):     Self.session_manager = session_manager     Self.request_handler = request_ Handler      try:       # Normal is to get all the data of the session, save it in sessiondata form       current_session = Session_manager.get (request_ Handler)     except invalidsessionexception:       # If the first access throws an exception, the exception is to get an empty Sessiondata object with no data, but contains the newly generated       # session_id and Hmac_key       current_session = Session_manager.get ()      # takes out the data in the Current_session and iterates     over it in the form of a key-value pair For key, data in Current_session.iteritems ():       Self[key] = Data      # Save under session_id     self.session_id = current _session.session_id     # and corresponding Hmac_key     self.hmac_key = Current_session.hmac_key    # define the Save method for session After the modified save, the actual call to Session_manager's Set method   def save (self):     


__init__ methods are difficult to understand, the basic process is to define their own Session_manager and handler processing objects. Then through the Session_manager to obtain the existing session data, using this data to initialize a user access session, if the user is the first access, then he got a new Sessiondata object, because there may be new users, so here to session_id and Hmac_key (what ghosts) are assigned.
The Save method is to provide a saving interface to modify the session data, actually call the Session_manager set method, the implementation is not considered.

Seeing these two classes, you should have a basic understanding of the work of the session, which can be considered from the user's access process. Note Basehandler This entry, each user's access is an HTTP request. When the user first accesses or the last session expires, at this time when the user accesses tornado established a handler object (the handler must inherit from Basehandler), and at the time of initialization a session object was established, because is the new access, the In the current session there is no data, after the use of key/value pairs in the form of reading and writing session (do not forget the session has all the dictionary operation), modified by the Save method saved session. If the user is not a new access, then the process is followed, but the session is initialized with the previous data taken out to save in the instance. When the user ends the access, HTTP disconnects, handler instances are destroyed, session instances are destroyed (note that the instance is destroyed, not data destroyed).

The following is ready to speak SessionManager Yes, come ~ a function to see ~

The first is initialization, setting the key, Memcache address, session timeout.

# initialization requires a secret for session encryption, Memcache address, session Expiration Time Def __init__ (self, secret, memcached_address, session_timeout):   Self.secret = Secret   self.memcached_address = memcached_address   

Next is the _fetch method, which extracts the data from the memcached with the session_id key and parses the data using pickle deserialization:

# This method uses session_id to remove data from Memcache def _fetch (self, session_id):   try:     # connect memcache server     mc = memcache. Client (self.memcached_address, debug=0)     # gets data     Session_data = Raw_data = Mc.get (session_id)     if raw_data! = None:       # in order to re       -refresh timeout mc.replace (session_id, Raw_data, self.session_timeout, 0)       # deserialization       session_ data = Pickle.loads (raw_data)     # Returns the If     type (session_data) = = Type ({}) if it is a dictionary form ({}):       return Session_ Data     Else:       return {}   except IOError:     

After a security check,


Get returns the memcached data (called the _fetch) method as Sessiondata.

def get (self, request_handler = none):    # gets the corresponding session_id and Hmac_key   if (request_handler = = None):     session_id = None     Hmac_key = none   else:     # The basis of the session is still by cookie     session_id = Request_handler.get_secure_cookie (" session_id ")     Hmac_key = Request_handler.get_secure_cookie (" verification ")    # session_id does not exist when it generates a new session_id and Hmac_key   if session_id = = None:     session_exists = False     session_id = self._generate_id ()     Hmac_key = Self._generate_hmac (session_id)   else:     session_exists = True    # Check for Hmac_key   check _hmac = Self._generate_hmac (session_id)   # does not pass then throws an exception   if Hmac_key! = Check_hmac:     raise Invalidsessionexception ()    # New Sessiondata Object   session = Sessiondata (session_id, Hmac_key)    if session_ exists:     # gets all the data for the session in Memcache by _fetch method     Session_data = Self._fetch (session_id) for     key, data in Session_data.iteritems ():       Session[key] = data    


As for the set method, it is to update the memcached data.

# set new session, need to set handler cookie and Memcache client def set (self, request_handler, session):   # Set Browser cookie   Reque St_handler.set_secure_cookie ("session_id", session.session_id)   Request_handler.set_secure_cookie (" Verification ", Session.hmac_key)   # is serialized with pickle   session_data = Pickle.dumps (Dict (Session.items ()), Pickle. Highest_protocol)   # connect memcache server   mc = memcache. Client (self.memcached_address, debug=0)   # write Memcache   


The last two functions, one is to generate session_id, and the other is to encrypt the session_id with the key to form an encrypted string for verification.

# generated session_id def _generate_id (self):   new_id = hashlib.sha256 (Self.secret + str (UUID.UUID4 ()))   return New_ Id.hexdigest ()  # Generate Hmac_key def _generate_hmac (self, session_id):   

Where did we initialize the SessionManager? Do you remember the application class in the first article? Oh... Go back and turn it over.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.