zdpgo_gin_jwt 专为zdpgo_gin打造的JWT权限校验中间件,当需要实现基于JWT Token的权限校验的时候可以考虑使用此框架

26 篇文章 1 订阅

zdpgo_gin_jwt

专为zdpgo_gin打造的JWT权限校验中间件,当需要实现基于JWT Token的权限校验的时候可以考虑使用此框架

使用教程

快速入门

package main

import (
	"log"
	"net/http"
	"os"
	"time"

	gin "github.com/zhangdapeng520/zdpgo_gin"
	jwt "github.com/zhangdapeng520/zdpgo_gin_jwt"
)

// 登录请求结构体
type login struct {
	Username string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

var (
	identityKey = "id"
	port        string
)

// User 用户模型
type User struct {
	UserName  string
	FirstName string
	LastName  string
}

func init() {
	port = os.Getenv("PORT")
	if port == "" {
		port = "8000"
	}
}

func main() {
	engine := gin.Default()

	// 创建中间件
	authMiddleware, err := jwt.New(initParams())
	if err != nil {
		log.Fatal("JWT Error:" + err.Error())
	}

	// 注册中间件
	engine.Use(handlerMiddleWare(authMiddleware))

	// 注册路由
	registerRoute(engine, authMiddleware)

	// 启动服务
	if err = http.ListenAndServe(":"+port, engine); err != nil {
		log.Fatal(err)
	}
}

// 注册路由
func registerRoute(r *gin.Engine, handle *jwt.GinJWTMiddleware) {
	r.POST("/login", handle.LoginHandler)               // 登录
	r.NoRoute(handle.MiddlewareFunc(), handleNoRoute()) // 404

	// 需要权限的路由
	auth := r.Group("/auth", handle.MiddlewareFunc())
	auth.GET("/refresh_token", handle.RefreshHandler)
	auth.GET("/hello", helloHandler)
}

// 处理中间件
func handlerMiddleWare(authMiddleware *jwt.GinJWTMiddleware) gin.HandlerFunc {
	return func(context *gin.Context) {
		errInit := authMiddleware.MiddlewareInit()
		if errInit != nil {
			log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error())
		}
	}
}

// 初始化中间件参数
func initParams() *jwt.GinJWTMiddleware {
	return &jwt.GinJWTMiddleware{
		Realm:       "test zone",
		Key:         []byte("secret key"),
		Timeout:     time.Hour,
		MaxRefresh:  time.Hour,
		IdentityKey: identityKey,
		PayloadFunc: payloadFunc(),

		IdentityHandler: identityHandler(),
		Authenticator:   authenticator(),
		Authorizator:    authorizator(),
		Unauthorized:    unauthorized(),
		TokenLookup:     "header: Authorization, query: token, cookie: jwt",
		// TokenLookup: "query:token",
		// TokenLookup: "cookie:token",
		TokenHeadName: "Bearer",
		TimeFunc:      time.Now,
	}
}

func payloadFunc() func(data interface{}) jwt.MapClaims {
	return func(data interface{}) jwt.MapClaims {
		if v, ok := data.(*User); ok {
			return jwt.MapClaims{
				identityKey: v.UserName,
			}
		}
		return jwt.MapClaims{}
	}
}

func identityHandler() func(c *gin.Context) interface{} {
	return func(c *gin.Context) interface{} {
		claims := jwt.ExtractClaims(c)
		return &User{
			UserName: claims[identityKey].(string),
		}
	}
}

// 校验账号密码
func authenticator() func(c *gin.Context) (interface{}, error) {
	return func(c *gin.Context) (interface{}, error) {
		var loginVals login
		if err := c.ShouldBind(&loginVals); err != nil {
			return "", jwt.ErrMissingLoginValues
		}
		userID := loginVals.Username
		password := loginVals.Password

		if userID == "zhangdapeng" && password == "zhangdapeng520" {
			return &User{
				UserName:  userID,
				LastName:  "Bo-Yi",
				FirstName: "Wu",
			}, nil
		}
		return nil, jwt.ErrFailedAuthentication
	}
}

func authorizator() func(data interface{}, c *gin.Context) bool {
	return func(data interface{}, c *gin.Context) bool {
		if v, ok := data.(*User); ok && v.UserName == "admin" {
			return true
		}
		return false
	}
}

func unauthorized() func(c *gin.Context, code int, message string) {
	return func(c *gin.Context, code int, message string) {
		c.JSON(code, gin.H{
			"code":    code,
			"message": message,
		})
	}
}

func handleNoRoute() func(c *gin.Context) {
	return func(c *gin.Context) {
		claims := jwt.ExtractClaims(c)
		log.Printf("NoRoute claims: %#v\n", claims)
		c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
	}
}

func helloHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	user, _ := c.Get(identityKey)
	c.JSON(200, gin.H{
		"userID":   claims[identityKey],
		"userName": user.(*User).UserName,
		"text":     "Hello World.",
	})
}

访问登录接口:

req -X POST -H 'Content-Type:application/json' -d '{\"username\":\"zhangdapeng\",\"password\":\"zhangdapeng520\"}' http://localhost:8000/login

访问hello接口:

req http://127.0.0.1:8000/hello

携带Token访问hello接口:

req -H 'Authorization: Bearer Token' http://127.0.0.1:8000/hello
req -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjM1MTMxOTIsImlkIjoiemhhbmdkYXBlbmciLCJvcmlnX2lhdCI6MTcyMzUwOTU5Mn0.gbFGsjCxFymMv4uQtVPmbOTiX8ScKONO80lfwZcAFEg' http://127.0.0.1:8000/hello

版本

v0.1.0

  • 基本用法

实际测试

在开发此框架的时候,我进行了实际的测试。

首先是访问登录接口:

req -X POST -H 'Content-Type:application/json' -d '{\"username\":\"zhangdapeng\",\"password\":\"zhangdapeng520\"}' http://localhost:8000/login

在这里插入图片描述

访问登录接口以后,会给我们返回一个Token,这个Token非常重要,是用来实现权限校验的重要信息。

接着,我们使用Token请求hello接口:

req -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjM1MTMxOTIsImlkIjoiemhhbmdkYXBlbmciLCJvcmlnX2lhdCI6MTcyMzUwOTU5Mn0.gbFGsjCxFymMv4uQtVPmbOTiX8ScKONO80lfwZcAFEg' http://127.0.0.1:8000/hello

在这里插入图片描述

如果我们访问hello接口的时候不携带Token是不会返回正确的信息的:

req http://127.0.0.1:8000/hello

在这里插入图片描述

当然,如果你传递的是一个错误的Token,也是不行的:

req -H 'Authorization: Bearer abc' http://127.0.0.1:8000/hello

在这里插入图片描述

更多资料

如果你需要更详细的视频课程或者一对一的私教指导,欢迎留言或者私信哈

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python私教

创业不易,请打赏支持我一点吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值