Using several web app development languages and frameworks, you will have access to the concept of session. Even the function of a simple site access count is often implemented using the session. Other areas of common use include shopping carts, login users, and more. However, the session has been a smattering, know it but do not know why.
After careful study of the HTTP protocol, as well as the Nodejs development stack of Express and express-session, I finally have a clear understanding of the session, but also to meet the development process over the years, often surfaced to the session of curiosity it.
This article uses Nodejs v9.5.0 as a technical validation tool. Before reading this article, you need to understand the basics of HTTP knowledge and cookie knowledge. Refer to rfc6265 for details, or read the last chapter of the HTTP book.
The concept of a session
A user's set of interrelated requests and responses on a site is one session. In short, this is the case:
- Session = A set of Access
- Access = Once request and response
For example, one of the simplest Nodejs HTTP programs:
http = require(‘http‘)http.createServer(function(req,res){ res.end(‘hello‘) }).listen(3000)
Each request goes to this handler: in this function, a request is made, the function(req,res){res.end(‘hello‘) }
response is processed, and the client is sent to a single access. Through the browser's developer tools, you can see the request content and response content for this session.
The use of site count as a case to illustrate, is that the same visitors from the same number of visits, you can get the current site access count.
Ingest session
We start by introducing the concept of conversation from a case. When we need to access features of the site count, we want users to visit this site:
- The first time you visit, your number of visits is 1
- Access count plus 1 for each subsequent visit
In this case, we need to have a place to store the current count so that when the same customer accesses it, the current count can be fetched, plus one back to the customer. Of course it is also necessary to identify this user (browser) and count each user separately. This means that when different users visit, they need to fetch the current count of the corresponding user.
The usual way to identify a customer's problem is to use cookies. Cookies are part of the HTTP protocol. HTTP can use the header field Set-cookie for a visitor to make a mark, which is often an ID, the next time you visit this site, HTTP through the cookie header field, send this ID to the site, this site know the identity of this customer and the status information associated with this identity, such as the current access count, or the contents of the current shopping cart, and so on.
Once the customer has been identified, it is possible to establish its unique status information within the Web server for this customer.
Implementing a session
Based on the Nodejs HTTP module, we implement a very simple session service. Just to show the concept, not for practical purposes. This service can implement a req.session variable that is shared over multiple accesses to the same site, which is an object that can write new members within this variable, or modify the values of existing member variables, and save req.session after each access so that the next access can get the current value:
var http =Require' http ')var SessionKey ="Sessionkey3" Http.createserver (functionReq,res) {if (Req.url = ="/") {session (Req,res) Req.session.count = (req.session.count+1) | |1 Res.end (' Hi ' +req.session.count)}Else Res.end (}). Listen (3000)Console.log (' Listen on 3000 ')functionSessionReq,res) {if (req.session)Returnvar answer, IDif (Issessionok (req)) {id = GetCookie (req) answer = Getsessionbyid (ID)}else{answer= {} id = createsession (answer) Setcookie (res,id)} req.session = Answer Res.on (' Finish ',function) {savesession (id,req.session)});}functionHascookie (Req) {Return (GetCookie (req)! =‘‘) }functionGetCookie (Req) {try{var C = req.headers[' Cookie ']var arr = C.split (‘;‘)for (var i =0; i < arr.length; i++) {var kv = Arr[i]var a = Kv.split (' = ')if (a[0].trim () = = SessionKey)Return a[1]}}catch (Error) {Return‘‘ }Return‘‘}functionSetcookie (Res,id) {Res.setheader ("Set-cookie", SessionKey +"=" +id)}var sessions = {}var sid =0functionGetsessionbyid (SID) {Return SESSIONS[SID]}function getsessionbyreq (req) { Span class= "Hljs-keyword" >var sid = GetCookie (req) return sessions[sid]}function createsession ( session) {sessions[sid++,session] return sid} function savesession (sid,session) {Sessions[sid] = session} function isSessionOk (req) {return Hascookie (req) && getsessionbyreq (req)!== undefined}
The program code is relatively simple, the reader can keep it to index.js, and then execute this program to verify the concept:
node index.js
Then, start Chrome, visit the site localhost:3000
, and then refresh multiple times, you can see each refresh, the number of visits returned gradually accumulated. When you open another browser, such as Safari, where you visit this site, you will find that the access count returned starts at 1 and counts in addition. Because it is two different in-browser, this guarantees that they are different access to the customer, the code within the site, will distinguish between the two, recording their status information separately.
The code uses an HTTP Cookie, and the basic algorithm is simple:
- If the session is not ready, then create a session, get the session ID, and send this ID to the browser via Set-cookie. This ID will be sent by the browser the next time you visit this site.
- If the session is ready, that is, the browser sends an ID through the cookie, and with this ID, the session can be obtained within the site
- Assigns the session created or acquired to the Req object
- The session object can be obtained and modified during the request processing function life cycle
- Save this session variable after the request has been processed
Perhaps you see sessionkey this variable, feel a little puzzled. The reason is that every time a cookie is sent, the same site may have multiple frames that need to use this cookie header field, such as php,aspx,jsp, etc. are needed to use, in order to appear not to conflict, we each use the cookie header field in each of the respective key/value pairs. For example, PHP key by default is phpsessid,express-session default is Connect.sid.
Summarize
This code demonstrates the concept of the most basic session, but is far from being a usable module and wants to use the session module in the real world, consider express-session.
There are a number of issues to consider when implementing a truly accessible session:
- The session ID used in this article is actually a self-increment integer. This leads to client spoofing, which hackers can guess SessionID, use forged SessionID to get the corresponding state data within the server, or forge logins for higher privileges. The real product is generally created with a guaranteed unique, hard-to-guess string.
- The session in this article will inevitably be saved after each end, regardless of whether the session is modified or not. The actual product needs to be considered for this optimization. At the same time, it is necessary to consider the expiration period of the session, to the expiration of the destruction, because some customers may come two times and then never come to visit, there is no need for them to save the status information, if you come again, you might as well recreate the session.
- The session in this article is saved in memory and once restarted, all sessions will be lost. In the actual product, it is necessary to support persistence of the preservation, such as saving to the MySQL database, Redis, MongoDB inside and so on. Therefore, a multi-provider scenario that requires data persistence is required.
Web Session shallow into shallow out (Shandong number diffuse lake)