1、AuthUtil.go : 用于生成和解析token
package utils
import (
"fmt"
"github.com/golang-jwt/jwt"
"time"
)
//自定义格式内容
type CustomerClaims struct {
UserId int `json:"userId"`
UserName string `json:"userName"`
RoleId int `json:"roleId"`
StandardClaims jwt.StandardClaims
}
func (c CustomerClaims) Valid() error {
return nil
}
//生成token
func GenerateJwtToken(secret string, issuer string, audience string, expiredMinutes int64, userId int, userName string, roleId int) (string, error) {
hmacSampleSecret := []byte(secret) //密钥,不能泄露
token := jwt.New(jwt.SigningMethodHS256)
nowTime := time.Now().Unix()
token.Claims = CustomerClaims{
UserName: userName,
UserId: userId,
RoleId: roleId,
StandardClaims: jwt.StandardClaims{
NotBefore: nowTime, // 签名生效时间
ExpiresAt: nowTime + expiredMinutes, // 签名过期时间
Issuer: issuer, // 签名颁发者
Audience: audience,
},
}
tokenString, err := token.SignedString(hmacSampleSecret)
return tokenString, err
}
//解析token
func ParseJwtToken(tokenString string, secret string) (*CustomerClaims, error) {
var hmacSampleSecret = []byte(secret)
//前面例子生成的token
token, err := jwt.ParseWithClaims(tokenString, &CustomerClaims{}, func(t *jwt.Token) (interface{}, error) {
return hmacSampleSecret, nil
})
if err != nil {
fmt.Println(err)
return nil, err
}
claims := token.Claims.(*CustomerClaims)
return claims, nil
}
//Config.go
type Config struct {
AppName string `json:"app_name"`
AppModel string `json:"app_model"`
AppHost string `json:"app_host"`
AppPort string `json:"app_port"`
Database DatabaseConfig `json:"database"`
RedisConfig RedisConfig `json:"redis_config"`
JwtConfig JwtConfig `json:"jwt_config"`
}
//Redis配置
type JwtConfig struct {
Issuer string `json:"issuer"`
Audience string `json:"audience"`
Expires int64 `json:"expires"`
SecretKey string `json:"secret_key"`
}
//app.json
"jwt_config": {
"issuer": "smallxiong",
"audience": "xiong",
"expires": 3600,
"secret_key": "54s64dede#$#1"
}
3、登录接口,别忘了加路由:不包含业务逻辑,只验证jwt功能
//登录
func (controller *UserController) Login(context *gin.Context) {
jwtConfig := config.GetConfig().JwtConfig
//生成token
token, err := utils.GenerateJwtToken(jwtConfig.SecretKey, jwtConfig.Issuer, jwtConfig.Audience, jwtConfig.Expires, 111, "小熊", 222)
if err != nil {
context.JSON(http.StatusOK, gin.H{"code": 500, "msg": "登录失败"})
}
//解析token
claims, err := utils.ParseJwtToken(token, jwtConfig.SecretKey)
if err != nil {
context.JSON(http.StatusOK, gin.H{"code": 500, "msg": "token解析失败"})
}
context.JSON(http.StatusOK, gin.H{"code": 200, "msg": "登录成功", "token": token, "claims": claims})
}
4、接口请求验证是否正常:
5、使用中间件校验jwt token: AuthMiddleware.go
package middleware
import (
config2 "gin_demo/config"
"gin_demo/utils"
"github.com/gin-gonic/gin"
"net/http"
"strings"
"time"
)
// 免登录接口列表
var notAuthArr = map[string]string{"/api/user/login": "1", "/api/user/get1": "1"}
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
inWhite := notAuthArr[c.Request.URL.Path]
if inWhite == "1" {
return
}
token := c.Request.Header.Get("Authorization")
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"status": -1, "msg": "请求未携带token,无权限访问"})
c.Abort()
return
}
if strings.HasPrefix(token, "Bearer") {
token = strings.Split(token, " ")[1]
}
config := config2.GetConfig()
// parse token, get the user and role info
claims, err := utils.ParseJwtToken(token, config.JwtConfig.SecretKey)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"status": -1, "msg": err.Error()})
c.Abort()
return
}
//token超时
if time.Now().Unix() > claims.StandardClaims.ExpiresAt {
c.JSON(http.StatusUnauthorized, gin.H{"status": -1, "msg": "token过期"})
c.Abort() //阻止执行
return
}
//可以在这里做权限校验
// 继续交由下一个路由处理,并将解析出的信息传递下去,可以在接口里获取:jwtUser, _ := context.Get("jwtUser")
c.Set("jwtUser", claims)
c.Next()
}
}
6、路由中配置中间件
router.Use(middleware.JWTAuth())