无法在Golang中读取cookie路由器:chi

问题描述

我正在使用todolist应用程序的REST API(并非来自教程),并且已经成功实现了身份验证,但是我的一个辅助功能似乎无法读取清晰可见的cookie,以下是该功能

// jwt is imported from the https://github.com/dgrijalva/jwt-go package
func validateAccesstoken(w http.ResponseWriter,r *http.Request) uuid.UUID {
    jwtSecret,exists := os.LookupEnv("JWT_SECRET")
    if !exists {
        w.WriteHeader(500)
        w.Write([]byte(`{"message":{"error":"Fatal internal error occurred"}}`))
        panic(errors.New("JWT_SECRET environment variable not set"))
    }
    // Get access token and then validate it
    at,err := r.Cookie("access_token")
    if err == http.ErrNoCookie {
        w.WriteHeader(401)
        w.Write([]byte(`{"message":{"error":"access_token cookie not found"}}`)) // this error is always returned when i attempt to use the handler that uses this function
        return uuid.Nil
    }
    t := at.Value
    token,err := jwt.ParseWithClaims(t,&models.UserClaims{},func(token *jwt.Token) (interface{},error) {
        return []byte(jwtSecret),nil
    })

    if claims,ok := token.Claims.(*models.UserClaims); ok && token.Valid {
        return claims.ID
    }
    w.WriteHeader(401)
    w.Write([]byte(`{"message":{"error":"access_token invalid"}}`))
    return uuid.Nil
}

这是设置cookie的代码的相关部分:

// Login handles the login route
func Login(w http.ResponseWriter,r *http.Request) {
    //...
    // Construct cookies and then set them
    rtCookie := http.Cookie{
        Name:    "refresh_token",Value:   *rt,Expires: time.Now().Add(time.Nanosecond * time.Duration(sessionLifeNanos)),}
    atCookie := http.Cookie{
        Name:    "access_token",Value:   *at,Expires: time.Now().Add(time.Minute * 15),}
    http.SetCookie(w,&rtCookie)
    http.SetCookie(w,&atCookie)
    w.Write([]byte(`{"message":"Logged in successfully :)"}`))
}

这是使用validateAccesstoken()的地方和失败的地方(uuid是“ github.com/google/uuid”包):

func CreateList(w http.ResponseWriter,r *http.Request) {
    // li will be used to store the decoded request body
    var li models.ListInput
    // listID will be used to store the returned id after inserting
    var listID uuid.UUID
    userID := validateAccesstoken(w,r)
    fmt.Println(userID.String())
    if userID == uuid.Nil {
        return
    }
    //...
}

此外,每当我在邮递员中使用登录路由后检查时,所有cookie都会发送到cookie罐中(并且没有“ access_token” cookie不会过期),并且具有正确的外观值。我对为什么validateAccesstoken()函数找不到其中的cookie感到困惑,这也是serve()调用main()函数

func serve() {
    // Initialise new router
    r := chi.NewRouter()
    // Some recommended middlewares
    r.Use(middleware.RequestID)
    r.Use(middleware.RealIP)
    r.Use(middleware.Logger)
    r.Use(middleware.Recoverer)
    // Cors options
    r.Use(cors.Handler(cors.Options{
        AllowedOrigins:   []string{"*"},AllowedHeaders:   []string{"*"},AllowedMethods:   []string{"GET","POST","PUT","DELETE","OPTIONS"},ExposedHeaders:   []string{"Content-Type","Set-Cookie","Cookie"},AllowCredentials: true,MaxAge:           300,}))
    // API routes
    r.Route("/api",func(r chi.Router) {
        r.Route("/users",func(r chi.Router) {
            r.Post("/",handlers.createuser)
            r.Post("/login",handlers.Login)
        })
        r.Route("/lists",handlers.CreateList)
        })
    })
    // Listen on port 5000 and log any errors
    log.Fatal(http.ListenAndServe("0.0.0.0:5000",r))
}

我非常感谢您提供的任何帮助,对于这个糟糕的问题,我深表歉意,我急于完成此工作。

解决方法

应用程序将cookie路径隐式设置为登录处理程序路径。通过将Cookie路径明确设置为“ /”来解决。

capitalize
,

我不确定,但是我认为该问题可能是由于SameSite Cookie策略引起的。 如果您正在使用现代浏览器版本从在不同端口上运行的前端测试程序,则可能是浏览器未发送Cookie,因为它们没有SameSite attribute

尝试将您的代码更改为:

rtCookie := http.Cookie{
        Name:    "refresh_token",Value:   *rt,SameSite: http.SameSiteNoneMode,Expires: time.Now().Add(time.Nanosecond * time.Duration(sessionLifeNanos)),}