英文:
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)
首先,让我们先纠正一些其他问题。
-
在type assertion中存在语法错误:
workspaceId, exists := user.(middleware.UserToken).WorkspaceID
应该改为:
userToken, exists := user.(middleware.UserToken) if exists { workspaceId := userToken.WorkspaceID }
-
根据
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.
-
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
> } -
According to
claims, ok := token.Claims.(*UserToken)
, theclaims
has the type*UserToken
instead ofUserToken
. Souser.(middleware.UserToken)
should beuser.(*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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论