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
更多资料
如果你需要更详细的视频课程或者一对一的私教指导,欢迎留言或者私信哈