我正在使用Youtube教程(GIN + GO + JWT)。我已经实现了令牌验证中间件。它运行良好,JWT配置的cookie与请求一起传递。如果没有令牌,它会阻塞带有401错误的请求,但也会导致500服务器错误。已经通过了JWT 文档,但无法解决这个问题。
中间件:
package middleware
import (
"fmt"
"net/http"
"os"
"time"
"github.com/fahad-md-kamal/go-jwt/initializers"
"github.com/fahad-md-kamal/go-jwt/models"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
)
func RequrieAuth(c *gin.Context) {
// Get the cookie off req
tokenString, err := c.Cookie("Authorization")
if err != nil {
c.AbortWithStatus(http.StatusUnauthorized)
}
// Decode/validate it
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(os.Getenv("SECRET")), nil
})
if token == nil {
// fmt.Println(token.Valid)
c.AbortWithStatus(http.StatusUnauthorized)
}
if claims, ok := token.Claims.(jwt.MapClaims); ok{
if float64(time.Now().Unix()) > claims["exp"].(float64){
c.AbortWithStatus(http.StatusUnauthorized)
}
// Find the user with token sub
var user models.User
initializers.DB.First(&user,claims["sub"])
if user.ID == 0 {
c.AbortWithStatus(http.StatusUnauthorized)
}
// Attach to req
c.Set("user", user)
// Continue
c.Next()
} else {
c.AbortWithStatus(http.StatusUnauthorized)
}
}错误:
2022/09/30 18:50:47 [Recovery] 2022/09/30 - 18:50:47 panic recovered:
GET /validate HTTP/1.1
Host: localhost:8000
Accept: */*
Accept-Encoding: gzip, deflate, br
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 102
Content-Type: application/json
Postman-Token: 9950b831-aa25-4ba3-a1eb-17c0fd8db5b4
User-Agent: PostmanRuntime/7.29.2
runtime error: invalid memory address or nil pointer dereference
/usr/local/opt/go/libexec/src/runtime/panic.go:260 (0x104c475)
panicmem: panic(memoryError)
/usr/local/opt/go/libexec/src/runtime/signal_unix.go:835 (0x104c445)
sigpanic: panicmem()
/Users/genex/Desktop/golang/jwt/middleware/requireAuth.go:37 (0x168016a)
RequrieAuth: if claims, ok := token.Claims.(jwt.MapClaims); ok{
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x166e361)
(*Context).Next: c.handlers[c.index](c)
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/recovery.go:101 (0x166e34c)
CustomRecoveryWithWriter.func1: c.Next()
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x166d466)
(*Context).Next: c.handlers[c.index](c)
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/logger.go:240 (0x166d449)
LoggerWithConfig.func1: c.Next()
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x166c530)
(*Context).Next: c.handlers[c.index](c)
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/gin.go:616 (0x166c198)
(*Engine).handleHTTPRequest: c.Next()
/Users/genex/golang/pkg/mod/github.com/gin-gonic/gin@v1.8.1/gin.go:572 (0x166bcdc)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/opt/go/libexec/src/net/http/server.go:2947 (0x12a7dab)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/opt/go/libexec/src/net/http/server.go:1991 (0x12a2fc6)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1594 (0x1067740)
goexit: BYTE $0x90 // NOP
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 401 with 500
[GIN] 2022/09/30 - 18:50:47 | 500 | 6.815587ms | ::1 | GET "/validate"发布于 2022-09-30 13:22:56
错误是第37行中的invalid memory address or nil pointer dereference。
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {那是因为token在这里是nil。(您可以写到,这是不带令牌的。)
上面写着在文档里
AbortWithStatus调用Abort()…中止阻止调用挂起的处理程序。请注意,这将不会停止当前处理程序的。(由我移情)
因此,您需要在调用return之后使用c.AbortWithStatus(http.StatusUnauthorized)语句,以便在发生错误时退出函数。
https://stackoverflow.com/questions/73909156
复制相似问题