从gin上下文中获取值

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

Retrieve value from gin context

问题

我有这段代码

package middleware

import (
	"net/http"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/irohitb/EmpAdmin/backend/domain"
)

type UserToken struct {
	jwt.StandardClaims
	User domain.UserToken
}

func SessionMiddleware(supabase_secret string) gin.HandlerFunc {
	return func(c *gin.Context) {
		userCookie, err := c.Cookie("user")
		if err != nil {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Missing user cookie"})
			return
		}

		token, err := jwt.ParseWithClaims(userCookie, &UserToken{}, func(token *jwt.Token) (interface{}, error) {
			return []byte(supabase_secret), nil
		})
		if err != nil {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Invalid user cookie"})
			return
		}

		claims, ok := token.Claims.(*UserToken)
		if !ok || !token.Valid {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Invalid user token"})
			return
		}

		if !claims.User.IsAdmin {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Only Admins can perform this action"})
			return
		}

		c.Set("user", claims)
		c.Next()
	}
}

现在,在我的路由器中,我如何获取使用c.Get("user")设置的值?

package services

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/irohitb/EmpAdmin/backend/config"
	"github.com/irohitb/EmpAdmin/backend/domain"
	"github.com/supabase/postgrest-go"
)

func GetAllUsers(env *config.Env, db *postgrest.Client, group *gin.RouterGroup) {
	group.GET("/:services", func(router *gin.Context) {
		services := strings.Split(router.Param("service"), ",")
		user, exists := router.Get("user")
		if !exists {
			router.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "user information not found in context"})
			return
		}

		workspaceId, exists := user.(middleware.UserToken).WorkspaceID
		if !exists {
			router.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "workspace_id not found in user information"})
			return
		}
	})
}

这里的这行代码引发了以下错误:

routes/services/users.go:16:3: services declared and not used
routes/services/users.go:24:54: user.(middleware.UserToken).WorkspaceID undefined (type middleware.UserToken has no field or method WorkspaceID)
英文:

I have this code

package middleware

import (
	"net/http"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/irohitb/EmpAdmin/backend/domain"
)




type UserToken struct {
	jwt.StandardClaims
	User domain.UserToken
}


func SessionMiddleware(supabase_secret string) gin.HandlerFunc {
	return func(c *gin.Context) {
		userCookie, err := c.Cookie("user")
		if err != nil {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Missing user cookie"})
			return
		}

		token, err := jwt.ParseWithClaims(userCookie, &UserToken{}, func(token *jwt.Token) (interface{}, error) {
			return []byte(supabase_secret), nil
		})
		if err != nil {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Invalid user cookie"})
			return
		}

		claims, ok := token.Claims.(*UserToken)
		if !ok || !token.Valid {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Invalid user token"})
			return
		}

		if !claims.User.IsAdmin {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "message": "Only Admins can perform this action"})
			return
		}

		c.Set("user", claims)
		c.Next()
	}
}

Now, in my router, how can I get value set using c.Get("user")?

package services

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/irohitb/EmpAdmin/backend/config"
	"github.com/irohitb/EmpAdmin/backend/domain"
	"github.com/supabase/postgrest-go"
)


func GetAllUsers(env *config.Env, db *postgrest.Client, group *gin.RouterGroup) {
	group.GET("/:services", func (router *gin.Context) {
		services := strings.Split(router.Param("service"), ",")
		user, exists := router.Get("user")
		if !exists {
        	router.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "user information not found in context"})
        	return
    	}

	
		workspaceId, exists := user.(middleware.UserToken).WorkspaceID
		 if !exists {
			router.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "workspace_id not found in user information"})
			return
    	}
		
	})
}

This line here is throwing the following error:

routes/services/users.go:16:3: services declared and not used
routes/services/users.go:24:54: user.(middleware.UserToken).WorkspaceID undefined (type middleware.UserToken has no field or method WorkspaceID)

答案1

得分: 2

这是一个编译时错误而不是运行时错误。说“这一行在这里抛出以下错误”是误导性的。

声明的服务未使用

这是Go语言中的一种实现限制,如果变量从未被使用,编译器可能会将在函数体内声明变量视为非法(参见语言规范)。要解决此问题,要么删除services变量,要么使用它。

user.(middleware.UserToken).WorkspaceID未定义(类型middleware.UserToken没有字段或方法WorkspaceID)

首先,让我们先纠正一些其他问题。

  1. type assertion中存在语法错误:

    workspaceId, exists := user.(middleware.UserToken).WorkspaceID
    

    应该改为:

    userToken, exists := user.(middleware.UserToken)
    if exists {
    	workspaceId := userToken.WorkspaceID
    }
    
  2. 根据claims, ok := token.Claims.(*UserToken)claims的类型应为*UserToken而不是UserToken。因此,user.(middleware.UserToken)应改为user.(*middleware.UserToken)

现在让我们回到错误。这意味着结构体middleware.UserToken没有WorkspaceID字段。也许WorkspaceID是结构体domain.UserToken的字段。假设是这种情况,整体修复应如下所示:

userToken, ok := user.(*middleware.UserToken)
if !ok {
	router.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": `router.Get("user") is not a UserToken`})
	return
}
workspaceId := userToken.User.WorkspaceId
// 在下面使用workspaceId
英文:

This is a compile time error instead of a runtime error. It's misleading to say that "This line here is throwing following error".

> services declared and not used

This is an implementation restriction in Go, A compiler may make it illegal to declare a variable inside a function body if the variable is never used (see the language spec). To fix this issue, either remove services or use it.

> user.(middleware.UserToken).WorkspaceID undefined (type middleware.UserToken has no field or method WorkspaceID)

Let's correct some other issues first.

  1. There is a syntax error in the type assertion:

    > go
    > workspaceId, exists := user.(middleware.UserToken).WorkspaceID
    >

    should be written as:

    > ```go
    > userToken, exists := user.(middleware.UserToken)
    > if exists {
    > workspaceId := userToken.WorkspaceID
    > }

  2. According to claims, ok := token.Claims.(*UserToken), the claims has the type *UserToken instead of UserToken. So user.(middleware.UserToken) should be user.(*middleware.UserToken).

Now let's turn back to the error. That means the struct middleware.UserToken does not have the field WorkspaceID. Maybe it's a field of the struct domain.UserToken. Let's assume this is the case, then the overall fix should be:

userToken, ok := user.(*middleware.UserToken)
if !ok {
	router.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": `router.Get("user") is not a UserToken`})
	return
}
workspaceId := userToken.User.WorkspaceId
// use workspaceId below

huangapple
  • 本文由 发表于 2023年4月30日 06:01:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76138645.html
匿名

发表评论

匿名网友

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

确定