go-gin集成session认证
常用的认证方式分为cookie/session/jwt,本文将演示golang的gin框架中如何集成session完成用户认证。
示例目录结构:
项目main入口:
package main
import (
"gin-any/api"
"github.com/gin-gonic/gin"
)
func main() {
engine := gin.Default()
engine.Use(api.EnableCookieSession()) // cookie as store
engine.POST("/login", api.Login)
engine.GET("/user", api.AuthSessionMiddleware(), api.User)
engine.Run(":8080")
}
认证接口:
package api
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
type ReqParams struct {
Username string `json:"username"`
Password string `json:"password"`
}
func User(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"code": 0,
"msg": "success",
"data": map[string]string{"user": "test"},
})
}
func Login(ctx *gin.Context) {
var params ReqParams
_ = ctx.ShouldBindBodyWith(¶ms, binding.JSON)
if params.Username == "test" && params.Password == "123456" {
sessionID := SaveSession(ctx, params.Username)
ctx.JSON(200, gin.H{
"code": 0,
"msg": "Login success",
"sessionID": sessionID,
})
return
}
ctx.JSON(401, gin.H{
"code": 1,
"msg": "Login failed",
})
}
中间件:
package api
import (
"crypto/sha256"
"fmt"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"strconv"
"time"
)
func AuthSessionMiddleware() gin.HandlerFunc {
return func(ctx *gin.Context) {
// extract session
sessionID := ctx.Request.Header.Get("Sessionid")
if sessionID == "" {
ctx.JSON(401, gin.H{
"code": 1,
"msg": "unauthorized",
})
ctx.Abort()
return
}
// set simple var
ctx.Set("sessionID", sessionID)
// validate session:1.check cache 2.check database // TODO
ctx.Next()
}
}
const KEY = "SESSIONSECRET"
func EnableCookieSession() gin.HandlerFunc {
store := cookie.NewStore([]byte(KEY))
return sessions.Sessions("Sample", store)
}
// register and login will save session
func SaveSession(ctx *gin.Context, username string) string {
session := sessions.Default(ctx)
// simple encrypt: sha256(usename + string(timestamp))
contact := username + strconv.FormatInt(time.Now().UnixMilli(), 10)
sum := sha256.Sum256([]byte(contact))
val := fmt.Sprintf("%x", sum)
session.Set("sessionID", val)
session.Save()
sessionID := session.Get("sessionID").(string)
ctx.Writer.Header().Set("sessionID", sessionID)
return sessionID
}
// logout will clear session
func ClearSession(ctx *gin.Context) {
session := sessions.Default(ctx)
session.Clear()
session.Save()
}
func HasSession(ctx *gin.Context) bool {
session := sessions.Default(ctx)
if val := session.Get("sessionID"); val == nil {
return false
}
return true
}
func GetSession(ctx*gin.Context) string {
session := sessions.Default(ctx)
val := session.Get("sessionID")
if val.(string) == "" {
return ""
}
return val.(string)
}