jwt项目中使用
第一步:在一个go文件中,写生成jwt和解析jwt的方法,方便调用
package jwt
import (
"errors"
"time"
"github.com/dgrijalva/jwt-go"
)
type Customclaims struct {
Empname string `json:"empname"`
Phone string `json:"phone"`
Role string `json:"role"`
jwt.StandardClaims
}
type MyClaims struct {
UserName string `json:"user_name"`
jwt.StandardClaims
}
var mySecret = []byte("呼哧呼哧")
func keyFunc(_ *jwt.Token) (i interface{}, err error) {
return mySecret, nil
}
const TokenExpireDuration = time.Hour * 24 * 365
func GenToken(userName string) (aToken, rToken string, err error) {
c := MyClaims{
userName,
jwt.StandardClaims{
ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(),
Issuer: "personal-blog",
},
}
aToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, c).SignedString(mySecret)
rToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Second * 30).Unix(),
Issuer: "personal-blog",
}).SignedString(mySecret)
return
}
func ParseToken(tokenString string) (claims *MyClaims, err error) {
var token *jwt.Token
claims = new(MyClaims)
token, err = jwt.ParseWithClaims(tokenString, claims, keyFunc)
if err != nil {
return
}
if !token.Valid {
err = errors.New("invalid token")
}
return
}
func RefreshToken(aToken, rToken string) (newAToken, newRToken string, err error) {
var claims MyClaims
_, err = jwt.ParseWithClaims(aToken, &claims, keyFunc)
return GenToken(claims.UserName)
}
第二步:登陆的时候生成token
func LoginHandler(c *gin.Context) {
var L models.Users
if err := c.ShouldBindJSON(&L); err != nil {
zap.L().Error("invalid params", zap.Error(err))
ResponseErrorWithMsg(c, CodeInvalidParams, err.Error())
return
}
var my models.Update_my
if err, a := mysql.Login(&L); err != nil {
zap.L().Error("mysql.Login(&u) failed", zap.Error(err))
ResponseError(c, CodeInvalidPassword)
return
} else {
my = a
}
aToken, rToken, _ := jwt.GenToken(L.UserName)
ResponseSuccess(c, gin.H{
"accessToken": aToken,
"refreshToken": rToken,
"username": L.UserName,
"role": L.Role,
"realname": my.Realname,
"phone_number": my.PhoneNumber,
"id_number": my.IDNumber,
})
}
第三步:在接口层中写一个go文件,JWTAuthMiddleware 基于JWT的认证中间件
package controller
import (
"Fever_backend/dao/mysql"
"Fever_backend/pkg/jwt"
"errors"
"fmt"
"go.uber.org/zap"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
const (
ContextUserNameKey = "userName"
)
var (
ErrorUserNotLogin = errors.New("当前用户未登录")
)
func JWTAuthMiddleware() func(c *gin.Context) {
return func(c *gin.Context) {
authHeader := c.Request.Header.Get("Authorization")
if authHeader == "" {
ResponseErrorWithMsg(c, CodeInvalidToken, "请求头缺少Auth Token")
c.Abort()
return
}
parts := strings.SplitN(authHeader, " ", 2)
if !(len(parts) == 2 && parts[0] == "Bearer") {
ResponseErrorWithMsg(c, CodeInvalidToken, "Token格式不对")
c.Abort()
return
}
mc, err := jwt.ParseToken(parts[1])
if err != nil {
fmt.Println(err)
ResponseError(c, CodeInvalidToken)
c.Abort()
return
}
c.Set(ContextUserNameKey, mc.UserName)
c.Next()
}
}
第四部:登陆验证token
v1.Use(controller.JWTAuthMiddleware())
{
v1.POST("/change_password", controller.ChangePasswordHandler)
v1.POST("/add_casbin", controller.AddCasbin)
}