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": "登录成功"})
}