Use in Go Session

Interaction throughout the client and server can be summarized as the following three steps:

  • The first time the client sends a request to the server to create Session, and generate a unique identifier SessionId
  • SessionId server will send to the client
    (in general there are two common ways: Cookie and URL rewriting)
  • When the client sends a request to the server again and SessionId sent to the server.

Go realize session

It does not provide an implementation of Sessoin in the Go standard library, so let's learn about the book by analyzing the example of "Go Web Programming" how to achieve a self-Session function.
(Ps: Although the standard library does not implement session, but there are many Web frameworks provide realization of the session)

The main realization Session to consider the following points:

  • Session created
  • Global Session Manager
  • SessionID global uniqueness
  • Session storage (can be stored into memory, files, databases, etc.)
  • Session expired deal

The following code example go along with the corresponding analyze the entire design ideas:

Defined Session:

Session uses a structure similar to the hash table (hash table is also possible) to save the information. If you have any Web development experience, you should know that only four operations Session: Set the value to get value, delete the value and access to current SessionID.
Session interface should therefore there are four ways to perform this operation:

type Session interface {
	Set(key, value interface{}) error //设置Session
	Get(key interface{}) interface{}  //获取Session
	Delete(key interface{}) error     //删除Session
	SessionID() string                //当前SessionID
}

Session can be preserved by a number of ways, including memory, files, databases and the like, so here defines a Session user interface, storage of different operating Session differently to achieve different.

Session Manager:

We know that Session data is stored in the server, so we can abstract a Provider Interface to represent the underlying structure of the Session Manager. Provider will access and manage Session by SessionID.

type Provider interface {
	SessionInit(sid string) (Session, error)
	SessionRead(sid string) (Session, error)
	SessionDestroy(sid string) error
	SessionGC(maxLifeTime int64)
}
  • SessionInit achieve Session initialization, if successful returns a new Session
  • SessionRead return Session represented by the corresponding sid, if not present, will call SessionInit sid way to create parameters and returns a new Session variable.
  • SessionDestroy given a sid, delete the Session.
  • SessionGC According Session variables maxLifeTime delete outdated

Good definition Provider Interface After that, we write a method of registration, so that we can be able to find its corresponding provider manager by name provider manager

the make Providers = var (Map [String] Provider) 

// can register a name to the acquired session provider manager 
FUNC RegisterProvider (String name, Provider Provider) { 
	IF Provider nil == { 
		panic ( "the session: the Register Provider IS nil ") 
	} 

	IF _, P: = Providers [name]; P { 
		panic (" the session: the Register Provider existed IS ") 
	} 

	Providers [name] = Provider 
}

  Provider then sent to packaging it, to define a global Session manager

struct {Manager of the type 
	cookieName String // name of the cookie 
	lock sync.Mutex // lock to ensure the safety of consistency of concurrent data 
	provider Provider // manage the session 
	maxlifetime int64 // timeout 
} 

FUNC NewManager (providerName, cookieName String, maxlifetime int64) (* Manager, error) { 
	Provider, OK: = Providers [providerName] 
	IF OK {! 
		return nil, fmt.Errorf ( "the session:? Provide% Unknown Q (Forgotten Import)", providerName) 
	} 

	// returns a Manager object 
	{& Manager return 
		the cookieName: the cookieName, 
		maxlifetime: maxlifetime, 
		Provider: Provider, 
	}, nil 
}

  Then create a global Session Manager in the main package

var globalSession *Manager

func init() {
	globalSession, _ = NewManager("memory", "sessionid", 3600)
}

  Unique Session ID

Session ID is used to identify each user to access the Web application, it is necessary to ensure that it is globally unique, the following sample code:

func (manager *Manager) sessionId() string {
	b := make([]byte, 32)
	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return ""
	}
	return base64.URLEncoding.EncodeToString(b)
}

  Creating Session

We need to allocate or obtain even Session associated with it for each user visiting, so as to verify the operation according to the Session back information. SessionStart This function is used to detect whether a Session has happened with the current visiting user is associated, if not create it.

// whether a valid session cookie is determined according to the current request does not exist, create 
FUNC (Manager * Manager) SessionStart (http.ResponseWriter W, R & lt http.Request *) (the Session session) { 
	// A method for locking 
	manager.lock.Lock () 
	the defer manager.lock.Unlock () 
	// get cookie values request in the request 
	cookie, ERR: = r.Cookie (manager.cookieName) 
	IF ERR = nil || cookie.Value == "! "{ 
		SID: = manager.sessionId () 
		the session, _ = manager.provider.SessionInit (SID) 
		Cookie: = {http.Cookie 
		the Name: manager.cookieName, 
		the Value: url.QueryEscape (SID), a special symbol // escape @ # ¥% + * - like 
		the Path: "/", 
		the HttpOnly: to true, 
		the MaxAge: int (manager.maxLifeTime)} 

		http.SetCookie (W, & cookie) // new cookie settings to the response 
	} else {
		sid, _ := url.QueryUnescape(cookie.Value)
		session, _ = manager.provider.SessionRead(sid)
	}
	return
}

  Now we have to return a variable Session interface to meet by SessionStart method. Here an example to show how the read and write operations Session:

// the user name of the user session is determined whether the presence, absence create 
FUNC Login (http.ResponseWriter W, R & lt http.Request *) { 
	Sess: globalSession.SessionStart = (W, R & lt) 
	r.ParseForm () 
	name: sess.Get = ( "username") 
	IF name! = nil { 
		sess.Set ( "username", r.Form [ "username"]) // value of the username submitted form is provided in the session 
	} 
}

  

Logout Session

In Web applications often have user logs out operation, then when the user exits the application, we will be able to log off the user's session data.

// SessionDestroy 注销 Session
func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(manager.cookieName)
	if err != nil || cookie.Value == "" {
		return
	}

	manager.lock.Lock()
	defer manager.lock.Unlock()

	manager.provider.SessionDestroy(cookie.Value)
	expiredTime := time.Now()
	newCookie := http.Cookie{
		Name: manager.cookieName,
		Path: "/", HttpOnly: true,
		Expires: expiredTime,
		MaxAge: -1,  //会话级cookie
	}
	http.SetCookie(w, &newCookie)
}

  Now we have to Session read (Get), write (Set), delete (Destroy) method of operation, the following combination of these three operations to show an example:

// record the number of the session is accessed 
FUNC COUNT (http.ResponseWriter W, R & lt http.Request *) { 
	Sess: globalSession.SessionStart = (W, R & lt) Example // Get session 
	createTime: = sess.Get ( "createTime" ) // get the session creation time 
	IF createTime nil == { 
		sess.Set ( "createTime", Time.now (). the Unix ()) 
	} the else IF (createTime. (Int64) + 360) <(Time.now () .Unix ()) {// expired 
		// logout old session information and a new globalSession.SessionDestroy session (W, R & lt) 
		Sess globalSession.SessionStart = (W, R & lt) 
	} 
	COUNT: = sess.Get ( "countnum") 
	IF COUNT == nil { 
		sess.Set ( "countnum",. 1) 
	} the else { 
		sess.Set ( "countnum", COUNT. (int) +. 1) 
	} 
}

  Delete Session

Then look at how Session Manager to delete Session.

// Open GC start function 
FUNC the init () { 
	Go globalSession.SessionGC () 
} 

FUNC (Manager * Manager) SessionGC () { 
	manager.lock.Lock () 
	the defer manager.lock.Unlock () 
	manager.provider.SessionGC (manager.maxLifeTime) 
	// time using a timer function package, it automatically calls the GC method when the session timeout 
	time.AfterFunc (time.Duration (manager.maxLifeTime), FUNC () { 
		manager.SessionGC () 
	}) 
}

  

Guess you like

Origin www.cnblogs.com/FSH1014/p/12585452.html