doujiaoang69440 2019-04-25 13:08
浏览 1323

如何在Golang中修复“ http:命名的cookie不存在”?

I'm building a small dinner/plan management application (with the use of microservices) for a couple of people I know. The intention is that each person can login to their own account and can then authenticate to other services using a bearer token (JWT).

This bearer token is stored in a cookie. However, I cannot find this cookie after it has been set and I try to retrieve it again.

Which eventually results in the error

http: named cookie not present

Why is the response body of the request empty? Why aren't there any cookies sent with my GET request? How can I go about fixing this?


I've searched around the net for a bit and tried the following things

  • Net/http cookie: The implementation that seems the most simple, and also the one that I'm showing here. It seems like this trivial example should work.

  • Cookiejar implementation: I tried to use the cookiejar implementation to set and retrieve the cookies from both the browser and postman, however it resulted in the same outcome. The cookiejar implementation I used is described in https://golang.org/pkg/net/http/cookiejar/?m=all#New

  • Setting to specific URL and extra GET request: I tried to place the cookies on a different specific URL within my domain. At some point it seemed like the cookies could only be retrieved from a certain specific absolute URL, this was not the case.

  • httputil DumpRequestOut: I found that the utility package of net/http had a function called DumpRequestOut, this function might have been able to extract the body from the request, but this was also empty.

  • Setting cookie 'secure' flag to false: I found a suggestion that the secure flag makes the cookies impossible to read. Unfortunately changing the secure flag had no effect.


Postman clearly shows that the cookies do exist. My browser (firefox) also shows that the cookies exist, but they have been given quite an abstract name. The Postman requests can be found at https://www.getpostman.com/collections/fccea5d5dc22e7107664

If I try to retrieve the cookies using the "net/http" package from golang, the response body comes up empty.

I set the session tokens and redirect the client directly after I've authenticated the user/password combination.

// SetTokenAndRedirect sets an access token to the cookies
func SetTokenAndRedirect(w http.ResponseWriter, r *http.Request, db *mgo.Session, u *user.User, redirectURL string) *handler.AppError {
    // Generate a unique ID for the session token.
    tokenID := uuid.Must(uuid.NewV4()).String()
    //set the expiration time (found in config.config.go)
    expirationTime := time.Now().Add(config.ExpireTime)
    // Set the cookie with the JWT
    http.SetCookie(w, &http.Cookie{
        Name:     config.AccessTokenName,
        Value:    createToken(u.UserID, expirationTime, tokenID, r.Header.Get("User-Agent")),
        Expires:  expirationTime,
        HttpOnly: true,
        Secure:   false,
    })

    // Redirects user to provided redirect URL
    if redirectURL == "" {
        return handler.AppErrorf(417, nil, "No redirect URL has been provided")
    }
    http.Redirect(w, r, redirectURL, 200)
    return nil
}

I try to verify the incoming request and JWT token as follows.

// All handlers will have this adapted serveHTTP function 
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if err := Authorize(w, r); err != nil {
        http.Error(w, fmt.Sprintf("Not Authorized: %v", err), http.StatusUnauthorized)
        return
    }
    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
        log.Printf("Handler error: status code: %d, message: %s, underlying err: %#v",
            e.Code, e.Message, e.Error)

        http.Error(w, e.Message, e.Code)
    }
}
// Claims defines what will be stored in a JWT access token
type Claims struct {
    ProgramVersion string `json:"programVersion"`
    UserAgent      string `json:"userAgent"`
    jwt.StandardClaims
}

// Authorize checks if the jwt token is valid
func Authorize(w http.ResponseWriter, r *http.Request) error {
    c, err := r.Cookie("access_token")
    if err != nil {
        if err == http.ErrNoCookie {
            // The program returns this error
            return err
        }
        return err
    }

    tokenString := c.Value

    claim := &Claims{}

    tkn, err := jwt.ParseWithClaims(tokenString, claim, func(tkn *jwt.Token) (interface{}, error) {
        return config.JwtSigningSecret, nil
    })
    if !tkn.Valid {
        return err
    }
    if err != nil {
        if err == jwt.ErrSignatureInvalid {
            return err
        }
        return err
    }

    // JWT token is valid
    return nil
}


The request is structured as follows when setting the cookie

// Pretty printed version
Host: localhost:8080
content-type: application/json
user-agent: PostmanRuntime/7.11.0
cache-control: no-cache
accept-encoding: gzip, deflate
content-length: 68
connection: keep-alive
accept: */*
postman-token: 36268859-a342-4630-9fb4-c286f76d868b
cookie: access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9ncmFtVmVyc2lvbiI6IjEuMC4wIiwidXNlckFnZW50IjoiUG9zdG1hblJ1bnRpbWUvNy4xMS4wIiwiZXhwIjoxNTU2MjA0MTg3LCJqdGkiOiJlZDlmMThhZi01NTAwLTQ0YTEtYmRkZi02M2E4YWVhM2M0ZDEiLCJpYXQiOjE1NTYyMDM1ODcsImlzcyI6ImdrLmp3dC5wcm9maWxlU2VydmljZS5hIn0.bssnjTZ8woKwIncdz_EOwYbCtt9t6V-7PmLxfq7GVyo
// Raw Version
&{POST /auth/users/login?redirect=/ HTTP/1.1 1 1 map[Cache-Control:[no-cache] Postman-Token:[d33a093e-c7ab-4eba-8c1e-914e85a0d289] Cookie:[access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9ncmFtVmVyc2lvbiI6IjEuMC4wIiwidXNlckFnZW50IjoiUG9zdG1hblJ1bnRpbWUvNy4xMS4wIiwiZXhwIjoxNTU2MjA0NDU4LCJqdGkiOiIzOTk1MmI1NS0yOWQzLTQ4NGQtODhhNC1iMDlhYmI1OWEyNzgiLCJpYXQiOjE1NTYyMDM4NTgsImlzcyI6ImdrLmp3dC5wcm9maWxlU2VydmljZS5hIn0.DFA7KBET3C2q1A9N1hXGMT0QbabHgaVcDBpAYpBdbi8] Accept-Encoding:[gzip, deflate] Connection:[keep-alive] Content-Type:[application/json] User-Agent:[PostmanRuntime/7.11.0] Accept:[*/*] Content-Length:[68]] 0xc0001ba140 <nil> 68 [] false localhost:8080 map[redirect:[/]] map[] <nil> map[] [::1]:36584 /auth/users/login?redirect=/ <nil> <nil> <nil> 0xc00016a2a0}

The request is structured as follows when getting the cookie

// Pretty printed version
Host: localhost:8080
cache-control: no-cache
postman-token: 20f7584f-b59d-46d8-b50f-7040d9d40062
accept-encoding: gzip, deflate
connection: keep-alive
user-agent: PostmanRuntime/7.11.0
accept: */*
// Raw version
2019/04/25 12:22:56 &{GET /path/provide HTTP/1.1 1 1 map[User-Agent:[PostmanRuntime/7.11.0] Accept:[*/*] Cache-Control:[no-cache] Postman-Token:[b79a73a3-3e08-48a4-b350-6bde4ac38d23] Accept-Encoding:[gzip, deflate] Connection:[keep-alive]] {} <nil> 0 [] false localhost:8080 map[] map[] <nil> map[] [::1]:35884 /path/provide <nil> <nil> <nil> 0xc000138240}

The response is structured as follows when setting the cooke

response Headers: map[Location:[/] Set-Cookie:[access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9ncmFtVmVyc2lvbiI6IjEuMC4wIiwidXNlckFnZW50IjoiR28taHR0cC1jbGllbnQvMS4xIiwiZXhwIjoxNTU2MjI4ODIyLCJqdGkiOiJlY2Q2NWRkZi1jZjViLTQ4N2YtYTNkYy00NmM3N2IyMmUzMWUiLCJpYXQiOjE1NTYyMjgyMjIsImlzcyI6ImdrLmp3dC5wcm9maWxlU2VydmljZS5hIn0.0sOvEzQS2gczjWSmtVSD_u0qMV2L7M4hKF1KUM08-bQ; Expires=Thu, 25 Apr 2019 21:47:02 GMT; HttpOnly] Date:[Thu, 25 Apr 2019 21:37:02 GMT] Content-Length:[0]]

I expect that the Authorize function will return nil. Also,if I add the following piece of code I expect that there are some cookies present.

for _, cookie := range r.Cookies() {
    fmt.Fprint(w, cookie.Name)
}

However, the Authorize function returns the error in the title and the printf does not print out any cookies.

  • 写回答

1条回答 默认 最新

  • douhuan6305 2019-04-25 15:39
    关注

    You are looking for the cookie by wrong name. Does config.AccessTokenName == "access_token"? (I think not). But you are trying to get the cookie with the cookie name access_token.

    This is an working example code, tested on both POSTMAN and Web browser.

    package main
    
    import (
        "log"
        "net/http"
        "time"
    )
    
    func main() {
    
        http.HandleFunc("/set", SetTokenAndRedirect)
    
        http.HandleFunc("/get", getToken)
    
        http.ListenAndServe(":8090", nil)
    
    }
    
    func SetTokenAndRedirect(w http.ResponseWriter, r 
    *http.Request) {
    
        expirationTime := time.Now().Add(time.Hour)
    // Set the cookie with the JWT
        http.SetCookie(w, &http.Cookie{
            Name:     "access_token", // you have to search 
    the cookie by this name
            Value:    "12378",
            Expires:  expirationTime,
            HttpOnly: true,
            Secure:   false,
        })
    
        redirectURL := "/"
    
        http.Redirect(w, r, redirectURL, 200)
    
    }
    
    func getToken(w http.ResponseWriter, r *http.Request) {
        c, err := r.Cookie("access_token")
    
        if err != nil {
            if err == http.ErrNoCookie {
                log.Println("Error finding cookie: ", err)
            }
            //handle the error gracefully
            log.Fatal(err)
        }
    
        tokenString := c.Value
    
        log.Println("Cookie found: ", tokenString)
    
    }
    

    For further experiment or if needed: Set the headers (including cookies) before anything else is written.

    A good discussion is could be found here

    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题