微信小程序+gorm+gin+jwt实现登录认证

step1:配置准备


##获取gin框架所需配置
go get github.com/gin-gonic/gin
##获取jwt所需配置
go get -u github.com/golang-jwt/jwt/v5
##获取gorm框架所需配置
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
 

step2:实现jwtToken认证


  1.定义解析结构

type Claim struct {
	gorm.Model
	jwt.RegisteredClaims
} //创建用户登录标签
var Msk []byte = []byte("nbyyyds666")//加密串

2.编译获取token的函数

//得到token,b 为加密串,c为用户id
func GetToken(b []byte, c uint) (string, error) { 
	a := Claim{
		gorm.Model{
			ID: c,
		},
		jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * 24 * time.Hour)),//过期时间
			Issuer:    "nb",//签发人
		},
	} //获取claim实例
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, a) //获取token
	return token.SignedString(b)                          //返回加密串
}

3.编译解析token的函数

//解析token
func ParseToken(a string) (*jwt.Token, *Claim, error) { 
	claim := &Claim{}
	t, err := jwt.ParseWithClaims(a, claim, func(t *jwt.Token) (interface{}, error) {
		return Msk, nil
	}) //接收前端发来加密字段
	return t, claim, err
}

step3:连接数据库


type User struct {
	gorm.Model
	Openid string
	Role   int
}//定义一个用户表
func GetDB() *gorm.DB {
	dsn := "root:1234@tcp(127.0.0.1:3306)/database?charset=utf8&parseTime=True&loc=Local"
//root为数据库根用户名,冒号后面为密码,database为数据库名称
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return db
} //打开数据库

step4:通过微信登录获取用户唯一的openid


1.定义所需结构

// WxSession 微信登陆接口返回session
type WxSession struct {
	SessionKey string `json:"session_key"`
	ExpireIn   int    `json:"expires_in"`
	OpenID     string `json:"openid"`
}

2.编译获取openid的函数

// WxLogin 微信用户授权
func (m User) WxLogin(jscode string) (session WxSession, err error) {
	client := &http.Client{}

	//生成要访问的url
	url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", "appid", "appsecret", jscode)

    //appid,appsecret可以从微信小程序前端获取
	//提交请求
	reqest, err := http.NewRequest("GET", url, nil)

	if err != nil {
		panic(err)
	}

	//处理返回结果
	response, e := client.Do(reqest)
	if e != nil {
		panic(e)
	}
	defer response.Body.Close()
	body, err := io.ReadAll(response.Body)

	jsonStr := string(body)
	//解析json
	if err := json.Unmarshal(body, &session); err != nil {
		session.SessionKey = jsonStr
		return session, err
	}

	return session, err
}

step5:gin的中间件


func Mid() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		t := ctx.GetHeader("Authorization") //得到头部请求的内容
		if t == "" || !strings.HasPrefix(t, "Bearer ") {
			ctx.JSON(401, "解析失败")
			ctx.Abort()
			return
		}

		t = t[7:]                 //扔掉头部
		tk, c, e := ParseToken(t) //c为claim结构体的实例
		if e != nil || !tk.Valid {
			ctx.JSON(401, "解析失败1")
			ctx.Abort() //中间件不通过
			return
		}
		Uid := c.Model.ID
		db := GetDB()
		var user4 User
		db.Where("ID=?", Uid).First(&user4)
		if user4.ID == 0 {
			ctx.JSON(401, "没有该用户")
			ctx.Abort()
			return
		}
		ctx.Set("user", user4)//把用户信息先储存,方便后续提取使用
		ctx.Next()//继续进行接下来的功能函数
	}

}

step6:登录函数


func Login(c *gin.Context) {
	user1 := new(User)
	jscode := c.Query("jscode")
	u, e := user1.WxLogin(jscode)//获取前端发来的jscode,并获取openid
	if e != nil {
		c.JSON(401, e)
		return
	}
	if u.OpenID == "" {
		c.JSON(400, "登录失败")
		return
	}
	db := GetDB()//开启数据库
	var user User
	db.Where("openid=?", u.OpenID).Find(&user)//查找数据库中是否已经有用户
	//如果没有则user.ID=0
    if user.ID == 0 {
		a := User{
			Openid: u.OpenID,
			Role:   0,
		}
		db.Create(&a)//在数据库中创建新用户
		db.Model(User{}).Where("openid=?", u.OpenID).Find(&user.ID)//重新获取
	}
//进行jwt加密,获取token返回给前端
	str, err := GetToken(Msk, user.ID)
	if err != nil {
		c.JSON(500, "加密失败")
		return
	}

	c.JSON(200, gin.H{
		"token":   str,
		"message": "登录成功"})
}

你可能感兴趣的:(golang,gin,开发语言)