基于gin的JWT跨域认证

写了一个demo

package main

import (
	"errors"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"strings"
	"time"
)

type UserInfo struct {
	Username string `json:"username" xml:"username" form:"username" binding:"required"`
	Password string	`json:"password" xml:"password" form:"password" binding:"required"`
}

type MyClaims struct {
	Username string
	jwt.StandardClaims
}
const TokenExpireDuration = time.Minute*10

var MySecret = []byte("mysecret")

func GenToken(username string) (string,error) {
	c := MyClaims{
		username,
		jwt.StandardClaims{
			ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(),
			Issuer: "my-project",
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256,c)
	return token.SignedString(MySecret)
}

func ParseToken(tokenString string) (*MyClaims,error) {
	token,err := jwt.ParseWithClaims(tokenString,MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return MySecret,nil
	})
	if err !=nil{
		return nil,err
	}
	if claims ,ok := token.Claims.(*MyClaims);ok && token.Valid{
		return claims,nil
	}
	return nil,errors.New("invalid token")
}

func authHandler(c *gin.Context) {
	var user UserInfo
	if err := c.ShouldBind(&user);err !=nil{
		c.JSON(http.StatusOK,gin.H{
			"code":2001,
			"msg":"无效的参数",
		})
		return
	}
//	校验
	if user.Username == "test" && user.Password == "test"{
		tokenString,_ := GenToken(user.Username)
		c.JSON(http.StatusOK,gin.H{
			"cooe":2000,
			"msg":"success",
			"data":gin.H{"token":tokenString},
		})
		return
	}
	c.JSON(http.StatusOK,gin.H{
		"code":2002,
		"msg":"鉴权失败",
	})
	return
}

//定义一个中间件,进行token的校验
func JWTAuthMiddleware() gin.HandlerFunc{
	return func(c *gin.Context) {
	//	携带token的三种方式: 1,放在请求头,2,放在请求体,3,放在url中
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == ""{
			c.JSON(http.StatusOK,gin.H{
				"code":2003,
				"msg":"请求体中auth为空",
			})
			c.Abort()
			return
		}
	//	按照空格分隔
		parts := strings.SplitN(authHeader," ",2)
		if !(len(parts) ==2 && parts[0] == "Bearer"){
			c.JSON(http.StatusOK,gin.H{
				"code":2005,
				"msg":"无效的token00",
			})
			c.Abort()
			return
		}
		// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
		mc,err := ParseToken(parts[1])
		if err !=nil{
			c.JSON(http.StatusOK,gin.H{
				"code":2005,
				"msg":"无效的token11",
			})
			c.Abort()
			return
		}
		c.Set("username",mc.Username)
		c.Next()
	}
}

func main() {
	r := gin.Default()
	r.Static("/static","./static")
	r.LoadHTMLGlob("templates/**/*")
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK,"login/login.html",nil)
	})

	r.POST("/auth",authHandler)

	r.GET("/home",JWTAuthMiddleware(), func(c *gin.Context) {
		username := c.MustGet("username")
		c.JSON(http.StatusOK,gin.H{
			"code":2000,
			"msg":"success",
			"data":gin.H{"username":username},
		})
	})

	if err := r.Run(":8081");err !=nil{
		log.Println("start failed err :",err)
	}
}

  

posted @ 2021-04-07 16:25  pebblecome  阅读(139)  评论(0)    收藏  举报