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

更多资料

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

相关推荐
栀夏61321 小时前
Kafka 快速入门
中间件
Dylanioucn1 天前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件
一水鉴天2 天前
智能工厂的软件设计 作为“程序Program”的中台
运维·人工智能·机器学习·中间件
加油,旭杏2 天前
【中间件学习】Nginx快速入门(为了配置一个项目)
学习·nginx·中间件
前端 贾公子2 天前
Express内置的中间件(express.json和express.urlencoded)格式的请求体数据
中间件·json·express
-XWB-3 天前
【安全漏洞-中间件】nginx版本号屏蔽
运维·nginx·中间件
小春学渗透3 天前
安全服务面试总结
安全·网络安全·中间件·安全服务
是曹大大3 天前
【RocketMQ】RocketMQ的特性(顺序、事务等)
java·中间件·rocketmq
上官花雨4 天前
第八章 中间件:SpringBoot 集成 Redis
spring boot·redis·中间件
加油,旭杏5 天前
【中间件】fastDFS的相关知识
中间件·fastdfs