JWT令牌已过期,但它没有过期时间。

huangapple go评论79阅读模式
英文:

JWT token expired but it doesnt have expiration time

问题

我正在使用golang进行简单的登录,我有一个路由用于使用golang-jwt库生成JWT令牌,但是当我尝试在中间件中验证令牌时,虽然它是有效的令牌,但它仍然告诉我令牌已过期,我不知道为什么。

这是我生成令牌的代码:

func GenerateToken(user models.User) (string, error) {
	tokenBuilder := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user":     user.Email,
		"nombre":   user.Nombre,
		"apellido": user.Apellido,
		"edad":     fmt.Sprint(user.Edad),
		"genero":   user.Genero,
		"rol":      user.Rol,
	})

	tokenBuilder.Claims.(jwt.MapClaims)["exp"] = nil

	tokenString, err := tokenBuilder.SignedString([]byte(os.Getenv("SECRET")))

	return tokenString, err
}

tokenBuilder.Claims.(jwt.MapClaims)["exp"] = nil 是我认为可以解决问题的地方,但是没有起作用。

我的中间件代码如下:

type CustomClaims struct {
	jwt.StandardClaims
}

func JWTMiddleware() fiber.Handler {
	return func(c *fiber.Ctx) error {
		authHeader := c.Get("Authorization")
		if authHeader == "" {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"message": "No Auth token",
			})
		}

		tokenString := authHeader[7:] // "Bearer "

		token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
			return []byte(os.Getenv("SECRET")), nil
		})

		if err != nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"message": "Invalid token",
			})
		}

		// 检查是否过期
		claims, ok := token.Claims.(*CustomClaims)
		if !ok || !token.Valid {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"message": "Invalid or expired",
			})
		}

		// 检查令牌过期时间
		if claims.ExpiresAt < time.Now().Unix() {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"message": "Expired token",
			})
		}

		return c.Next()
	}
}

我真的不知道我的生成的令牌是否正确,或者我的中间件是否正确,在这个中间件中,我尝试捕获没有过期时间的令牌,我刚开始学习golang,我进行了调查,但是我还是不明白,这个令牌可以与库创建的中间件一起使用,但是我想要自己的中间件用于不同的目的。谢谢,祝你有愉快的一天,希望我表达清楚。

英文:

I'm working in a simple login with golang i have a route that generates a token jwt with library golang-jwt but when i try to verify the token in a middleware, yes it is a valid token but it keep telling me that is expired, i don't know why

this is my code for generate the token:

func GenerateToken(user models.User) (string, error) {
	tokenBuilder := jwt.NewWithClaims(jwt.SigningMethodHS256 , jwt.MapClaims{
		&quot;user&quot;:user.Email,
		&quot;nombre&quot;:user.Nombre,
		&quot;apellido&quot;:user.Apellido,
		&quot;edad&quot;:fmt.Sprint(user.Edad),
		&quot;genero&quot;:user.Genero,
		&quot;rol&quot;:user.Rol,
	})

	tokenBuilder.Claims.(jwt.MapClaims)[&quot;exp&quot;] = nil

	tokenString, err := tokenBuilder.SignedString([]byte(os.Getenv(&quot;SECRET&quot;)))

	return tokenString,err
	
}

tokenBuilder.Claims.(jwt.MapClaims)[&quot;exp&quot;] = nil it was what i think solve the problem. but didn't work

And my middleware is this

type CustomClaims struct {
	jwt.StandardClaims
}

func JWTMiddleware() fiber.Handler {
	return func(c *fiber.Ctx) error {
		authHeader := c.Get(&quot;Authorization&quot;)
		if authHeader == &quot;&quot; {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				&quot;message&quot;: &quot;No Auth token&quot;,
			})
		}

		tokenString := authHeader[7:] //&quot;Bearer &quot;

		token , err := jwt.ParseWithClaims(tokenString, &amp;CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
			return []byte(os.Getenv(&quot;SECRET&quot;)), nil
		})

		if err != nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				&quot;message&quot;: &quot;Invalid token&quot;,
			})
		}

		//Check if is expired
		claims, ok := token.Claims.(*CustomClaims)
		if !ok || !token.Valid {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				&quot;message&quot;: &quot;Invalid or expired&quot;,
			})
		}

		// Check token expiration time
		if claims.ExpiresAt &lt; time.Now().Unix() {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				&quot;message&quot;: &quot;Expired token&quot;,
			})
		}

		return c.Next()
	}
}

I don't really know if my generated token is right or my middleware is right, in this middleware i try to catch tokens even if this doesn't have expiration time, I'm starting in golang, i investigated but im out, this token work with the middleware created by library but i want mines for different purposes. Thank you and good day i hope i have been clear

I try tokenBuilder.Claims.(jwt.MapClaims)[&quot;exp&quot;] = nil and in my tokenGeneration make a new claim like this exp:0

答案1

得分: 2

如果您不设置exp,那么StandardClaims.ExpiresAt将采用其默认值(int64类型,即0),因此claims.ExpiresAt < time.Now().Unix()将为truetime.Now().Unix()将大于0!)。如果您真的想这样做,那么可以添加一个检查0的条件,例如:

if claims.ExpiresAt != 0 && claims.ExpiresAt < time.Now().Unix() {

值得注意的是,ParseWithClaims会验证exp(所以您实际上不需要验证!)。请注意,它会调用Valid,因此"如果令牌中的任何声明都不存在,仍将被视为有效声明"。

更好的选择是设置一个有效的过期时间...

另外,创建一个Minimal, Reproducible, Example,例如这个,可能会让您得出这个结论(如果没有让您的问题更简单)。

英文:

If you don't set exp then StandardClaims.ExpiresAt will be it's default value (int64 so 0) and, as such, claims.ExpiresAt &lt; time.Now().Unix() will be true (time.Now().Unix() will be greater than 0!). If you really want to do this then add a check for 0 e.g.

if claims.ExpiresAt != 0 &amp;&amp; claims.ExpiresAt &lt; time.Now().Unix() {

It's worth noting that ParseWithClaims verifies exp (so you don't really need to!). Note that it will call Valid so "if any of the above claims are not in the token, it will still be considered a valid claim.".

A better option would be to set a valid expiry...

As a further note creating a Minimal, Reproducible, Example such as this would probably have led you to this conclusion (and if not made your question simpler).

huangapple
  • 本文由 发表于 2023年4月21日 02:49:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76067342.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定