middle/cors.go
package middle
import (
"net/http"
"github.com/gin-gonic/gin"
)
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
//获取请求方法
method := c.Request.Method
//添加跨域响应头
c.Header("Content-Type", "application/json")
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Max-Age", "86400")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
c.Header("Access-Control-Allow-Headers", "X-Token, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-Max")
c.Header("Access-Control-Allow-Credentials", "false")
//放行OPTIONS方法
if method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
//处理请求
c.Next()
}
}
验证请求的合法性,前端只有在登录状态下才会生成token,请求时将token放入Header中,后端接收的请求时,先由该中间件验证token是否合法,合法时才放行,继续执行业务函数的逻辑处理。
utils/jwt.go
package utils
import (
"errors"
"github.com/dgrijalva/jwt-go"
"github.com/wonderivan/logger"
"golang.org/x/oauth2/jwt"
)
var JWTToken jwtToken
type jwtToken struct{}
//定义token中携带的信息
type CustomClaims struct {
Username string `json:"username"`
Password string `json:"password"`
jwt.StandardClaims
}
//加解密因子
const (
SECRET = "adoodevops"
)
//解析Token
func (*jwtToken) ParseToken(tokenString string) (claims *CustomClaims, err error) {
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(SECRET), nil
})
if err != nil {
logger.Error("parse token failed ", err)
//处理token解析后的各种错误
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
return nil, errors.New("TokenMalformed")
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
return nil, errors.New("TokenExpired")
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
return nil, errors.New("TokenNotValidYet")
} else {
return nil, errors.New("TokenInvalid")
}
}
}
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("解析Token失败")
}
middle/jwt.go
package middle
import (
"k8s-plantform/utils"
"github.com/gin-gonic/gin"
"net/http"
)
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
//对登录接口放行
if len(c.Request.URL.String()) >= 10 && c.Request.URL.String()[0:10] == "/api/login" {
c.Next()
} else {
//处理验证逻辑
token := c.Request.Header.Get("Authorization")
if token == "" {
c.JSON(http.StatusBadRequest, gin.H{
"msg": "请求未携带token,无权限访问",
"data": nil,
})
c.Abort()
return
}
//解析token内容
claims, err := utils.JWTToken.ParseToken(token)
if err != nil {
//token过期错误
if err.Error() == "TokenExpired" {
c.JSON(http.StatusBadRequest, gin.H{
"msg": "授权已过期",
"data": nil,
})
c.Abort()
return
}
//其他解析错误
c.JSON(http.StatusBadRequest, gin.H{
"msg": err.Error(),
"data": nil,
})
c.Abort()
return
}
c.Set("claims", claims)
c.Next()
}
}
}
main.go
package main
import (
"fmt"
"k8s-plantform/config"
"k8s-plantform/controller"
"k8s-plantform/db"
"k8s-plantform/middle"
"k8s-plantform/service"
"github.com/gin-gonic/gin"
)
func main() {
// 初始化数据库
db.Init()
// 初始化k8s client
service.K8s.Init()
// 初始化gin
r := gin.Default()
// 加载jwt中间件
r.Use(middle.JWTAuth())
// 加载跨域中间件
r.Use(middle.Cors())
// 初始化路由
controller.Router.InitApiRouter(r)
// gin 程序启动
//r.Run(config.ListenAdd)
fmt.Println("http://192.168.31.1:9091/")
r.Run(config.ListenAddr)
// 关闭数据库
db.Close()
}
测试再访问就会提示:“请求未携带token,无权限访问”