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

zdpgo_gin_jwt

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

使用教程

快速入门

go 复制代码
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.",
	})
}

访问登录接口:

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

访问hello接口:

bash 复制代码
req http://127.0.0.1:8000/hello

携带Token访问hello接口:

bash 复制代码
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

  • 基本用法

实际测试

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

首先是访问登录接口:

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

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

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

bash 复制代码
req -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjM1MTMxOTIsImlkIjoiemhhbmdkYXBlbmciLCJvcmlnX2lhdCI6MTcyMzUwOTU5Mn0.gbFGsjCxFymMv4uQtVPmbOTiX8ScKONO80lfwZcAFEg' http://127.0.0.1:8000/hello

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

bash 复制代码
req http://127.0.0.1:8000/hello

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

bash 复制代码
req -H 'Authorization: Bearer abc' http://127.0.0.1:8000/hello

更多资料

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

相关推荐
青火coding6 小时前
SOFAServerless架构的意义
java·运维·中间件·架构·serverless
kite01211 天前
GIn + Casbin: RBAC 权限控制系统集成
gin·jwt·casbin
马士兵教育1 天前
AI大模型通用智能体项目从原理到落地:Agent Skills 的核心逻辑与中间件 + 动态工具实践方案+架构项目实战!
人工智能·中间件·架构
米优4 天前
使用Qt实现消息队列中间件动态库封装
c++·中间件·rabbitmq
小丑小丑小丑4 天前
【AP AUTOSAR】COM通信模块api详解
中间件·汽车·autosar·autosar ap
信创天地4 天前
信创环境下数据库与中间件监控实战:指标采集、工具应用与告警体系构建
java·运维·数据库·安全·elk·华为·中间件
小唐同学爱学习5 天前
布隆过滤器
java·spring boot·中间件
flyyyya5 天前
【AI学习从零至壹】langchain1.0中间件
人工智能·学习·中间件
General_G6 天前
irobot_benchmark的编译和使用
linux·中间件·机器人·ros2
burning_maple6 天前
设计数据密集型应用阅读笔记
分布式·后端·中间件