Session cookies, some authentication mechanisms of gin framework

Posted by ColinP on Wed, 09 Feb 2022 08:16:51 +0100

gin.Cookie() use

The following small example can use postman to request. As long as the service is started, it is mainly the cookie function to get the value of the request header and the SetCookie function to set the value of the cookie

func main() {
  r := gin.Default()
  r.Get("/cookie", handler.MyHandler)
  r.Run(":8080")
}
func MyHandler(c *gin.Context) {
  // Get cookie key_ value corresponding to cookie
  cookie_value, err := c.Cookie("my_cookie")
 
  if err != nil {
    cookie_value = "no value"
    // cookie settings
    c.SetCookie("my_cookie", cookie_value, 3600, "/", "localhost", false, true)
  }
  
  // Then we can look in the response header. result is the key of the response header and the cookie_value is the value of the response header
  c.Header("result", cookie_value)
}

gin.BasicAuth() middleware

As follows, the key is to use the map of secrets, which can be imagined as the data in the database, and then add the middleware gin to a routing packet Basicauth(), this middleware needs to trigger the middleware identification when accessing the interface in packet routing, and then get the user name through c.MustGet() when logging in, search the user name in the "database" and match the password. If successful, the user logs in and returns to normal json

// Simulate some private data
var secrets = gin.H{
	"foo":    gin.H{"email": "foo@bar.com", "phone": "123433"},
	"austin": gin.H{"email": "austin@example.com", "phone": "666"},
	"lena":   gin.H{"email": "lena@guapa.com", "phone": "523443"},
}

func main() {
	r := gin.Default()

	// Routing groups use gin Basicauth () middleware
	// gin.Accounts is a shortcut to map[string]string
	authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
		"foo":    "bar",
		"austin": "1234",
		"lena":   "hello2",
		"manu":   "4321",
	}))

	// /admin/secrets endpoint
	// Trigger "localhost:8080/admin/secrets"
	authorized.GET("/secrets", func(c *gin.Context) {
		// Get the user, which is set by BasicAuth middleware
		user := c.MustGet(gin.AuthUserKey).(string)
		if secret, ok := secrets[user]; ok {
			c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})
		} else {
			c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})
		}
	})

	// Listen and start the service on 0.0.0.0:8080
	r.Run(":8080")
}

github. COM / gin contrib / sessions package

Although we need to introduce GitHub COM / gin contrib / sessions package, but actually this package also belongs to the gin Gonic group

r := gin.Default()

// It is introduced in the middle. This secret is mainly used to generate a key. You can specify a string at will
store := cookie.NewStore([]byte("secret"))
// Specifies the name of the cookie for the browser side response header
r.Use(sessions.Sessions("SESSIONID222", store))

After the login is successful and the session set value is, the set cookie field will appear in the response header returned by the interface, in which the internal key is SESSIONID222, as shown in the following figure

Then the browser will save the contents of the cookie, and the cookie will be carried in the request header when requesting later, as shown below

This method of authentication has been defined above. How to save login information after login? As follows, in a HandlerFunc

username := c.PostForm("username")
password := c.PostForm("password")

// If all database queries exist and are correct
if (username == "aaa" && password == "bbb") {
  s := sessions.Default(c)
  // Set the session of this user
  s.Set("user", username)
  // preservation
  s.Save()
} else {
  // todo: xxx
}

In this way, you can determine whether the session of s.Get("user") exists in some pages to determine whether there is login

s := sessions.Default(c)
// Get the data in the requester's session
username := s.Get("user")
if username != nil {
  // todo: xxx
} else {
  // todo: yyy
}

Summarize the core idea: every time you log in for the first time, the requester does not have a request header with a cookie. At this time, the back end will judge whether the user password meets the requirements of the database. After matching, the user information will be stored in the session, and then the set cookie field will be returned in the request response header, which contains the session information, Then, all subsequent requests will carry the request header of the cookie, which contains the information of the previous session. In this way, each subsequent request can determine whether the information in the session has been stored in the back-end session. If it has been stored, it can be accessed. If you log out later, the back-end actually empties the session storage. In this way, even if the front-end comes with the request header of the cookie, there is still no data in the back-end session, so it is determined that there is no login and therefore cannot be accessed

In fact, it can be vividly understood that when you log in for the first time, it is equivalent to a person who does not have an ID card to apply for an ID card from the government, and then the government department (back end) stores the ID card data, and then returns the ID card to you personally (back to the front end), and then you can do things with only one ID card every time you go to various government departments, If the government department deletes the identification of your ID card for some reasons (log out and clear the session at the back end), you can't work in various government departments even with your ID card, so you need to find the government department to apply for a new ID card (log in again)

Authentication method used in actual production

In practice, JWT authentication or oauth2 package is mainly used for authentication

JWT is very commonly used. I will explain in another blog post how to use JWT for authentication

Topics: Go Session cookie