• 基于gin的golang web开发:实现用户登录


    前文分别介绍过了Restygin-jwt两个包,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
    }
    

    好了准备工作到此结束,下面来看一下如何实现登录功能。

    实现认证

    首先实现调用查询用户服务的方法。

    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验证的部分。

    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一文中有详细的解释,我们重点来看一下用户验证的部分:Authenticator

    方法ShouldBind对参数进行模型绑定,不熟悉模型绑定的话可以查看前文基于gin的golang web开发:模型绑定。然后调用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开发:实现用户登录

  • 相关阅读:
    BackupPC备份
    H5日常使用
    无互联网环境安装docker
    docker 部署zabbix
    docker: error pulling image configuration:
    java web开发入门六(spring mvc)基于intellig idea
    java web开发入门七(mybatis)基于intellig idea
    java web开发入门九(Maven使用&idea创建maven项目)基于intellig idea
    Intellij IDEA使用一 创建javaweb项目并配置tomcat
    java web开发入门四(spring)基于intellig idea
  • 原文地址:https://www.cnblogs.com/huaface/p/14120655.html
Copyright © 2020-2023  润新知