1. 程式人生 > >基於gin的golang web開發:實現使用者登入

基於gin的golang web開發:實現使用者登入

前文分別介紹過了[Resty][1]和[gin-jwt][2]兩個包,```Resty```是一個HTTP和REST客戶端,```gin-jwt```是一個實現了JWT的Gin中介軟體。本文將使用這兩個包來實現一個簡單的使用者登入功能。 ### 環境準備 實現登入功能之前要提前準備一個用於查詢使用者是否存在的服務。訪問服務```http://127.0.0.1:18081/users?username=root```時返回使用者root的相關資訊 ``` { "total": 1, "data": [ { "id": 1, "username": "root", "password": "CGUx1FN++xS+4wNDFeN6DA==", "nickname": "超級管理員", "mobile": "13323232323" } ] } ``` 返回結果中```password```欄位AES加密後的結果。當引數```username```傳入其他字串時返回```null``` ``` { "total": 0, "data": null } ``` 好了準備工作到此結束,下面來看一下如何實現登入功能。 ### 實現認證 首先實現呼叫查詢使用者服務的方法。 ```golang func FindUser(userName string) (user sysUser.SysUser, err error) { client := resty.New().SetRetryCount(3) resp, err := client.R(). SetQueryParams(map[string]string{ "username": userName, }). SetResult(&PagedUser{}). Get("http://127.0.0.1:18081/users") if err != nil { log.Panicln("FindUser err: ", err.Error()) } response := resp.Result().(*PagedUser) if response.Total == 1 { user = response.Data[0] return } err = errors.New("使用者不存在") return } ``` 這裡我們建立了一個```Resty```客戶端,並設定了3次重試,依照服務的要求傳入```username```引數,然後通過```Total```值判斷使用者是否存在,使用者存在的話返回使用者資訊,否則返回錯誤。 接下來我們實現有關jwt驗證的部分。 ```golang var identityKey = "id" type login struct { Username string `form:"username" json:"username" binding:"required"` Password string `form:"password" json:"password" binding:"required"` } type User struct { Id int UserName string NickName string } func JwtMiddleware() (authMiddleware *jwt.GinJWTMiddleware, err error) { authMiddleware, err = jwt.New(&jwt.GinJWTMiddleware{ Realm: "test zone", Key: []byte("secret key"), Timeout: time.Hour, MaxRefresh: time.Hour, IdentityKey: identityKey, PayloadFunc: func(data interface{}) jwt.MapClaims { if v, ok := data.(*User); ok { return jwt.MapClaims{ identityKey: v.UserName, } } return jwt.MapClaims{} }, IdentityHandler: func(c *gin.Context) interface{} { claims := jwt.ExtractClaims(c) return &User{ UserName: claims[identityKey].(string), } }, Authenticator: func(c *gin.Context) (interface{}, error) { var loginVals login if err := c.ShouldBind(&loginVals); err != nil { return "", jwt.ErrMissingLoginValues } userID := loginVals.Username password := loginVals.Password user, err := http_service.FindUser(userID) if err != nil { return nil, jwt.ErrFailedAuthentication } encrypt := utils.PasswordEncrypt(password, userID) if encrypt != user.Password.String { return nil, jwt.ErrFailedAuthentication } return &User{ Id: user.Id, UserName: user.Username.String, NickName: user.Nickname.String, }, nil }, Authorizator: func(data interface{}, c *gin.Context) bool { if v, ok := data.(*User); ok && v.UserName == "admin" { return true } return false }, Unauthorized: func(c *gin.Context, code int, message string) { c.JSON(code, gin.H{ "code": code, "message": message, }) }, TokenLookup: "header: Authorization, query: token, cookie: jwt_middleware", TokenHeadName: "Bearer", TimeFunc: time.Now, }) return } ``` 以上程式碼在[基於gin的golang web開發:認證利器jwt][1]一文中有詳細的解釋,我們重點來看一下使用者驗證的部分:```Authenticator```。 方法```ShouldBind```對引數進行模型繫結,不熟悉模型繫結的話可以檢視前文[基於gin的golang web開發:模型繫結][3]。然後呼叫```FindUser```方法檢查使用者是否存在,如果使用者存在的話還需要驗證一下使用者密碼是否正確。全部驗證通過返回```User```結構體,進入```gin-jwt```的後續流程。 最後一步在Gin中增加使用者登入路由。 ``` func main() { r := gin.Default() authMiddleware, err := JwtMiddleware() if err != nil { log.Fatal("JWT Error:" + err.Error()) } errInit := authMiddleware.MiddlewareInit() if errInit != nil { log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error()) } r.POST("/login", authMiddleware.LoginHandler) r.Run(":8090") } ``` 大功告成,現在呼叫```/login```介面,並提供正確的使用者名稱和密碼,不出意外的話會得到一個成功的JSON,裡面包含了驗證通過的JWT。 文章出處:[基於gin的golang web開發:實現使用者登入][source] [source]: https://www.huaface.com/article/27 [1]: https://www.huaface.com/article/24 [2]: https://www.huaface.com/article/26 [3]: https://www.huaface.com/art