This is a creation in Article, where the information may have evolved or changed.
Article transferred from https://blog.csdn.net/lzy_zhi_yuan/article/details/73127601
Go there is no official session, so only to encapsulate the session manager, specific steps see code comments, will be in the following article to explain the actual combat.
Session operation interface, different storage mode sesion operation different, implementation also different type Session interface {Set (key, Value interface{}) Get (key interface{}) Inter face{} Remove (key interface{}) error GetId () string}//session implementation type Sessionfrommemory struct {sid s Tring//Unique flag lock sync. Mutex//A mutex lock lastaccessedtime time. Time//Last access MaxAge Int64//Timeout time data map[interface{} ]interface{}//Master data}//instantiation func newsessionfrommemory () *sessionfrommemory {return &sessionfrommemory{data: Make (map[interface{}]interface{}), maxage:60 * 30,//default 30 minutes}}//the same session can be called, set up, the operation must have the exclusion lock func (Si *sessionfromm Emory) Set (key, Value interface{}) {Si.lock.Lock () defer si.lock.Unlock () Si.data[key] = Value}func (si *session frommemory) Get (Key interface{}) interface{} {if value: = Si.data[key]; Value! = nil {return value} RET Urn Nil}func (si *sessionfrommeMory) Remove (key interface{}) error {if value: = Si.data[key]; Value! = nil {Delete (Si.data, key)} Retu RN Nil}func (Si *sessionfrommemory) GetId () string {return si.sid}//session storage interface, which can be stored in memory, database, or file//implement the interface separately//as stored in the database Crud operation type Storage interface {//initialize a session,id as needed after incoming initsession (SID string, MaxAge Int64) (Session, error) Based on SID, get current session setsession (session session) error//Destroy session destroysession (SID string) error//Reclaim GCS Ession ()}//session from memory type frommemory struct {//Because the session contains all the requests//and rows, the data is guaranteed to be independent, consistent, and secure lock sync. Mutex//Mutex sessions map[string]session}//instantiation of a Memory implementation func Newfrommemory () *frommemory {return &frommemory{ Sessions:make (map[string]session, 0),}}//Initial swap session, this structural gymnastics implementation Session interface func (FM *frommemory) initsession (Sid Strin G, MaxAge Int64) (Session, error) {Fm.lock.Lock () defer fm.lock.Unlock () NewSession: = Newsessionfrommemory () Newsession.sid = SID If MaxAge! = 0{newsession.maxage = maxAge} newsession.lastaccessedtime = time. Now () Fm.sessions[sid] = newsession//memory management map return newsession, nil}//set func (FM *frommemory) setsession (Session Se Ssion) Error {fm.sessions[session. GetId ()] = Session return nil}//destroy SESSIONFUNC (FM *frommemory) destroysession (SID string) Error {If _, OK: = fm.ses SIONS[SID]; OK {Delete (fm.sessions, sid) return nil} return nil}//Supervisor timeout func (FM *frommemory) gcsession () {ses Sions: = Fm.sessions//fmt. PRINTLN ("GC session") If Len (sessions) < 1 {return}//fmt. PRINTLN ("Current active sessions", sessions) for k, V: = Range Sessions {t: = (V. (*sessionfrommemory). Lastacce Ssedtime.unix ()) + (V. (*sessionfrommemory). MaxAge) If T < time. Now (). Unix () {//timed out the FMT. PRINTLN ("Timeout-------->", v) Delete (fm.sessions, k)}}}//--------------Session_manager--------- -------------//Management session, actual operation Cookie,storageBecause the structure is the entire application level, write, modify all need to shackle type SessionManager struct {//session data eventually needs to be stored in a cookie when the client (browser) and server each save a copy//client Cookien Ame string//storage mode, such as memory, database, file storage Storage//Timeout time MaxAge Int64//due to the session containing all requests//and rows, ensure data independence, consistency, security Lock sync. mutex}//instantiation of a session manager Func Newsessionmanager () *sessionmanager {sessionmanager: = &sessionmanager{Cookien Ame: "Lzy-cookie", Storage:newfrommemory (),//default memory implementation MAXAGE:60 * 30,//default 30 min} go s ESSIONMANAGER.GC () return Sessionmanager}func (M *sessionmanager) Getcookien () string {return m.cookiename}//First judge the current please If there is a valid session in the cookie, there is a return, there is no create func (M *sessionmanager) beginsession (w http). Responsewriter, R *http. Request) Session {//Prevent processing, enter additional request M.lock.lock () defer m.lock.unlock () cookie, err: = R.cookie (M.cookiename) If err! = Nil | | Cookies. Value = = "" {//if the current request does not change the cookie name corresponding to the cookie FMT. Println ("-----------> Current session NOT EXISTS")//Create a Sid: = M.randomid ()//based on save session mode, such as memory, session created in database, _: = M.storage.initsession (SID, M.maxage)//The method has its own Locks, multiple calls to MaxAge: = M.maxage if MaxAge = = 0 {MaxAge = session. *sessionfrommemory). MaxAge}//Use the session ID in the cookie associated//cookie name and expiration time by the session manager to maintain the cookie: = Htt p.cookie{Name:m.cookiename,//This is concurrency insecure, but this method is locked value:url. Queryescape (SID),//Escape special symbol @#¥%+*-, etc. Path: "/", Httponly:true, Maxage:int (MaxAge), Expires:time. Now (). ADD (time. Duration (MaxAge)), HTTP. Setcookie (W, &cookie)//Set in response to return session} else {//If there is a SID, _: = URL. Queryunescape (cookies. Value)//Invert the special symbol session: = M.storage. (*frommemory). Sessions[sid]//Obtain FMT from the save session media. Println ("Session--------->", session) if session = = Nil {fmt. Println ("-----------> Current session is nil") Create a//sid: = M.randomid ()//based on save session mode, such as memory, create NewSession in database, _: = M.storage. Initsession (SID, M.maxage)//The method has its own lock, multiple calls to MaxAge: = M.maxage if MaxAge = = 0 {maxag E = newsession. (*sessionfrommemory). MaxAge}//Use the session ID in the cookie Association//cookie name and expiration time maintained by the session Manager Newcookie: = http. cookie{Name:m.cookiename,//This is concurrency insecure, but this method is locked value:url. Queryescape (SID),//Escape special symbol @#¥%+*-, etc. Path: "/", Httponly:true, Maxage:i NT (MaxAge), Expires:time. Now (). ADD (time. Duration (MaxAge)), HTTP. Setcookie (W, &newcookie)//Set into response in return newsession} FMT. Println ("-----------> Current session exists") Return session}}//Update timeout func (M *sessionmanager) Update (w http. Responsewriter, R *http. Request) {M.lock.lock () Defer M.lock.unlock () cookie, err: = R.cookie (m.cookiename) if err! = nil {return} t: = time. Now () sid, _: = URL. Queryunescape (cookies. Value) Sessions: = M.storage. (*frommemory). Sessions session: = Sessions[sid]. (*sessionfrommemory) Session.lastaccessedtime = t Sessions[sid] = Session if M.maxage! = 0 {cookie. MaxAge = Int (m.maxage)} else {cookie. MaxAge = Int (session.maxage)} http. Setcookie (w, cookie)}//gets Sessionfunc (M *sessionmanager) Getsessionbyid (SID string) by ID, session {session: = M.storage. (*frommemory). Sessions[sid] Return session}//If there is a func (M *sessionmanager) memoryisexists (SID String) bool {_ In memory, OK : = M.storage. (*frommemory). Sessions[sid] If OK {return true} return false}//manually destroy session, delete Cookiefunc (M *sessionman Ager) Destroy (w http. Responsewriter, R *http. Request) {cookie, err: = R.cookie (m.cookiename) if err! = Nil | | cookie. Value = = "" {return} else { M.lock.lock () defer m.lock.unlock () sid, _: = URL. Queryunescape (cookies. Value) m.storage.destroysession (SID) Cookie2: = http. cookie{maxage:0, Name:m.cookiename, Value: "", Path: "/", Expires:time. Now (). ADD (time. Duration (0)),} http. Setcookie (W, &cookie2)}}func (M *sessionmanager) cookieisexists (R *http. Request) BOOL {_, Err: = R.cookie (m.cookiename) if err! = Nil {return false} return true}//open each session while Timed call this method//to reach the session maximum life, and time-out. Recycle it func (M *sessionmanager) GC () {m.lock.lock () defer m.lock.unlock () m.storage.gcsession ()///After how long it takes to execute an anonymous function, here A GC time is executed after a certain period. Afterfunc (time. Duration (M.MAXAGE*10), func () {M.GC ()})}//whether to put the session into memory (operating memory) By default is Operation memory func (M *sessionmanager) isfrommemory () { M.storage = Newfrommemory ()}//whether to put session into database (Operation database) func (M *sessionmanager) Isfromdb () {//todo//About storage database not implemented}FU NC (M *sessionmanager) SeTmaxage (t int64) {m.maxage = t}//If you implement the method of saving the session yourself, you can adjust the function to define func (M *sessionmanager) setsessionfrom (Storage storage {m.storage = storage}//generates a certain length of random number func (M *sessionmanager) Randomid () string {b: = make ([]byte, +) If _, err : = Io. Readfull (Rand. Reader, B); Err! = Nil {return ""}//Encrypt return base64. Urlencoding.encodetostring (b)
The above encapsulation method also has the similar specific reference https://www.cnblogs.com/chevin/p/5669940.html
540 reads ∙1 likes