0

0

如何解决 Go 聊天应用程序中 cookie 未在本地主机端口之间传输的问题?

王林

王林

发布时间:2024-02-05 22:39:11

|

1185人浏览过

|

来源于stackoverflow

转载

如何解决 go 聊天应用程序中 cookie 未在本地主机端口之间传输的问题?

问题内容

我在聊天应用程序中遇到基于 cookie 的令牌身份验证问题。我正在使用带有标准网络库的 go 后端来将令牌添加到响应 cookie。当用户通过密码验证(通过 post 到身份验证服务器上的 /login 路径)时,响应 cookie 应包含用于生成 api 令牌的访问令牌和用于重新生成访问令牌的刷新令牌。

这是一个标记文件,其中包含我的开发环境中应用程序服务的结构。每个服务器都在本地主机上使用 go net/http 在顺序端口上运行(不显示不相关的服务)。

auth_server (
    dependencies []
    url (scheme "http" domain "localhost" port "8081")
    listenaddress ":8081"
    endpoints (
        /jwtkeypub (
            methods [get]
        )
        /register (
            methods [post]
        )
        /logout (
            methods [post]
        )
        /login (
            methods [post]
        )
        /apitokens (
            methods [get]
        )
        /accesstokens (
            methods [get]
        )
    )
    jwtinfo (
        issuername "auth_server"
        audiencename "auth_server"
    )
)

message_server (
    dependencies [auth_server]
    url (scheme "http" domain "localhost" port "8083")
    listenaddress ":8083"
    endpoints (
        /ws (
            methods [get]
        )
    )
    jwtinfo (
        audiencename "message_server"
    )
)

static (
    dependencies [auth_server, message_server]
    url (scheme "http" domain "localhost" port "8080")
    listenaddress ":8080"
)

这是在登录时设置 cookie 的代码。密码检查后会发生这种情况

// set a new refresh token
    refreshtoken := s.jwtissuer.stringifyjwt(
        s.jwtissuer.minttoken(userid, s.jwtissuer.name, refreshtokenttl),
    )
    kit.sethttponlycookie(w, "refreshtoken", refreshtoken, int(refreshtokenttl.seconds()))

    // set a new access token
    accesstoken := s.jwtissuer.stringifyjwt(
        s.jwtissuer.minttoken(userid, s.jwtaudience.name, accesstokenttl),
    )
    kit.sethttponlycookie(w, "accesstoken", accesstoken, int(accesstokenttl.seconds()))
}
func sethttponlycookie(w http.responsewriter, name, value string, maxage int) {
    http.setcookie(w, &http.cookie{
        name:     name,
        value:    value,
        httponly: true,
        maxage:   maxage,
    })
}

以下是当用户请求 api 令牌时我如何访问 cookie。如果返回错误,处理程序将调用 gettokenfromcookie() 函数并以 401 进行响应。这种情况下的错误是“http:命名的cookie不存在”

func gethttpcookie(r *http.request, name string) (*http.cookie, error) {
    return r.cookie(name)
}

func gettokenfromcookie(r *http.request, name string) (jwt.jwt, error) {
    tokencookie, err := gethttpcookie(r, name)
    if err != nil {
        // debug
        log.println(err)
        return jwt.jwt{}, err
    }

    return jwt.fromstring(tokencookie.value)
}

来自登录端点的 200 响应后,页面重定向到主应用程序页面。在此页面上,向身份验证服务器发出请求以接收用于连接实时聊天消息服务器的 api 令牌。从auth服务器上的日志输出可以看到,请求中没有收到访问令牌cookie,因此请求返回401代码。

2023/05/19 02:33:57 get [/jwtkeypub] - 200
2023/05/19 02:33:57 get [/jwtkeypub] - 200
2023/05/19 02:34:23 post [/login] - 200
2023/05/19 02:34:23 http: named cookie not present
{{ } {    } []} http: named cookie not present
2023/05/19 02:34:23 get [/apitokens?aud=msgservice] - 401

我相信问题在于我使用的是 localhost,并且浏览器不会将 cookie 从 locahost:8080 传输到 localhost:8081。我正计划实现某种模拟身份验证,绕过读取开发环境的 cookie 来解决这个问题,但我不确定这是否真的是我的问题的原因。只是想再看一下,看看我是否可以让它工作而不需要这样做。

更新:我已经查看了开发工具中的网络选项卡: 图像显示登录后的响应返回了 cookie,但它们随后不会发送到端口 8081 上的身份验证服务器。在获得登录的 200 响应后,我还查看了 cookie 存储,即使在之后也没有 cookie在响应中接收它们。我正在使用 firefox 的私人模式来访问该网站。请注意,即使我在 go 代码中设置了 maxage,cookie 也不包含 maxage,这似乎是一个问题。

更新:这是登录后的 har 文件。您可以看到响应有 max-age,但之后它不会显示在 cookies 选项卡中。

{
  "log": {
    "version": "1.2",
    "creator": {
      "name": "Firefox",
      "version": "113.0.1"
    },
    "browser": {
      "name": "Firefox",
      "version": "113.0.1"
    },
    "pages": [
      {
        "startedDateTime": "2023-05-19T12:16:37.081-04:00",
        "id": "page_1",
        "title": "Login Page",
        "pageTimings": {
          "onContentLoad": -8105,
          "onLoad": -8077
        }
      }
    ],
    "entries": [
      {
        "pageref": "page_1",
        "startedDateTime": "2023-05-19T12:16:37.081-04:00",
        "request": {
          "bodySize": 31,
          "method": "POST",
          "url": "http://0.0.0.0:8081/login",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Host",
              "value": "0.0.0.0:8081"
            },
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0"
            },
            {
              "name": "Accept",
              "value": "*/*"
            },
            {
              "name": "Accept-Language",
              "value": "en-US,en;q=0.5"
            },
            {
              "name": "Accept-Encoding",
              "value": "gzip, deflate"
            },
            {
              "name": "Referer",
              "value": "http://localhost:8080/"
            },
            {
              "name": "Content-Type",
              "value": "text/plain;charset=UTF-8"
            },
            {
              "name": "Content-Length",
              "value": "31"
            },
            {
              "name": "Origin",
              "value": "http://localhost:8080"
            },
            {
              "name": "DNT",
              "value": "1"
            },
            {
              "name": "Connection",
              "value": "keep-alive"
            }
          ],
          "cookies": [],
          "queryString": [],
          "headersSize": 370,
          "postData": {
            "mimeType": "text/plain;charset=UTF-8",
            "params": [],
            "text": "{\"username\":\"a\",\"password\":\"a\"}"
          }
        },
        "response": {
          "status": 200,
          "statusText": "OK",
          "httpVersion": "HTTP/1.1",
          "headers": [
            {
              "name": "Access-Control-Allow-Origin",
              "value": "*"
            },
            {
              "name": "Set-Cookie",
              "value": "refreshToken=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJQMmY2RHg1RWxlYTF5THBUaVpEejBaS3Z1dk1FUkFPZEtBVGkwNDZSc2JNPSIsImF1ZCI6InN0ZWVsaXgiLCJpc3MiOiJzdGVlbGl4IiwiZXhwIjoiMTY4NTExNzc5NyIsImp0aSI6IjIwMUQzODZDNTRBQzlEOUMwRjdCODFBMDVDNDlFQTE1In0.SbxFgEAtZbh0zS-SXZmrVW9iLk-cFz6HcDMU0FHNl-K9BwCeb_boc5igEgImMSYK-NBVQZh1km7YknE-jkBWyF0rIYjSnTzjNUHHwMnn0jE1N-dtEfNRnF1OT0R2bxPSz8gmhtJ3B839xa-jh9uMPMkXEB8BYtABgPH1FqBdijHPUtRVKq6C3ulVleurp2eyF8EHpGLc9rr5wBYSFBk0HQ3FNjjUxfRQLDnzl2xYovoQ2em4grExnkdACxCSpXNtF5bQ7lCnEZyf7-CehrRNwZCpteGKj5ux_wrX_nxma3OEWwrlatML_j-e420TM1tub0C9Ymyt0bMugHw8vaiOGA; Max-Age=604800; HttpOnly"
            },
            {
              "name": "Set-Cookie",
              "value": "accessToken=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJQMmY2RHg1RWxlYTF5THBUaVpEejBaS3Z1dk1FUkFPZEtBVGkwNDZSc2JNPSIsImF1ZCI6InN0ZWVsaXgiLCJpc3MiOiJzdGVlbGl4IiwiZXhwIjoiMTY4NDUxNDE5NyIsImp0aSI6IjY2NjU1QjAyNTc4NkRBRTE1M0VDNDI3MzBGMjMxQ0FGIn0.cIs6KGjRGTHaWX_uFTts_V2a3YcBb7LA0jNOBTZeyDmpPQgRlcABnuYkWUIdjUdR6VYnDitFRV-XK2ZSq6Pk_ZgyfvJ3yRzvWGYjXMu7Nq7MLpVvUh9mLKSbKvlqunW6YVamHSCAbYS8-D_pY9fpWxIcXw0qbwA2XfTdzr0Mrw7ntrkdyK7O1QqWamnEHCmpLfJ2XJlQsU0KaD8FjkL76pO3lWmrca3VYnTmjP1Oo1HEhbK3nImtrNeL2khAyb8ns8ROj2HX41IDNK1aHWPfn9J04pgH3AfBfcwhhqZkrKjTVFQAkSYzuvjKPWOfpgYmBMw3Y5nG_PDf-zlvVPrdpQ; Max-Age=1200; HttpOnly"
            },
            {
              "name": "Date",
              "value": "Fri, 19 May 2023 16:16:37 GMT"
            },
            {
              "name": "Content-Length",
              "value": "0"
            }
          ],
          "cookies": [
            {
              "name": "refreshToken",
              "value": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJQMmY2RHg1RWxlYTF5THBUaVpEejBaS3Z1dk1FUkFPZEtBVGkwNDZSc2JNPSIsImF1ZCI6InN0ZWVsaXgiLCJpc3MiOiJzdGVlbGl4IiwiZXhwIjoiMTY4NTExNzc5NyIsImp0aSI6IjIwMUQzODZDNTRBQzlEOUMwRjdCODFBMDVDNDlFQTE1In0.SbxFgEAtZbh0zS-SXZmrVW9iLk-cFz6HcDMU0FHNl-K9BwCeb_boc5igEgImMSYK-NBVQZh1km7YknE-jkBWyF0rIYjSnTzjNUHHwMnn0jE1N-dtEfNRnF1OT0R2bxPSz8gmhtJ3B839xa-jh9uMPMkXEB8BYtABgPH1FqBdijHPUtRVKq6C3ulVleurp2eyF8EHpGLc9rr5wBYSFBk0HQ3FNjjUxfRQLDnzl2xYovoQ2em4grExnkdACxCSpXNtF5bQ7lCnEZyf7-CehrRNwZCpteGKj5ux_wrX_nxma3OEWwrlatML_j-e420TM1tub0C9Ymyt0bMugHw8vaiOGA"
            },
            {
              "name": "accessToken",
              "value": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJQMmY2RHg1RWxlYTF5THBUaVpEejBaS3Z1dk1FUkFPZEtBVGkwNDZSc2JNPSIsImF1ZCI6InN0ZWVsaXgiLCJpc3MiOiJzdGVlbGl4IiwiZXhwIjoiMTY4NDUxNDE5NyIsImp0aSI6IjY2NjU1QjAyNTc4NkRBRTE1M0VDNDI3MzBGMjMxQ0FGIn0.cIs6KGjRGTHaWX_uFTts_V2a3YcBb7LA0jNOBTZeyDmpPQgRlcABnuYkWUIdjUdR6VYnDitFRV-XK2ZSq6Pk_ZgyfvJ3yRzvWGYjXMu7Nq7MLpVvUh9mLKSbKvlqunW6YVamHSCAbYS8-D_pY9fpWxIcXw0qbwA2XfTdzr0Mrw7ntrkdyK7O1QqWamnEHCmpLfJ2XJlQsU0KaD8FjkL76pO3lWmrca3VYnTmjP1Oo1HEhbK3nImtrNeL2khAyb8ns8ROj2HX41IDNK1aHWPfn9J04pgH3AfBfcwhhqZkrKjTVFQAkSYzuvjKPWOfpgYmBMw3Y5nG_PDf-zlvVPrdpQ"
            }
          ],
          "content": {
            "mimeType": "text/plain",
            "size": 0,
            "text": ""
          },
          "redirectURL": "",
          "headersSize": 1347,
          "bodySize": 1748
        },
        "cache": {},
        "timings": {
          "blocked": 0,
          "dns": 0,
          "connect": 0,
          "ssl": 0,
          "send": 0,
          "wait": 13,
          "receive": 0
        },
        "time": 13,
        "_securityState": "insecure",
        "serverIPAddress": "0.0.0.0",
        "connection": "8081"
      }
    ]
  }
}

响应似乎有 cookie,但它们没有被保存。

并且对身份验证服务器的下一个请求没有添加任何 cookie。

MiniMax Agent
MiniMax Agent

MiniMax平台推出的Agent智能体助手

下载

正确答案


tl;dr

  1. cookie 不会在 0.0.0.0localhost 之间共享。
  2. 会话 cookie 和普通 cookie 都可以在 http://localhost:8080http://localhost:8081 之间共享。
  3. http://localhost:8080/ 页面发送到 http://localhost:8081/ 的请求将被视为跨域请求。
  4. fetch 发送的跨域请求应使用 credentials: 'include' 进行初始化,以使浏览器保存 cookie。

har显示网页的url为http://localhost:8080/,但登录端点为http://0.0.0.0:8081/login0.0.0.0 的 cookie 不会与 localhost 共享。

您可以运行下面的演示来观察行为:

  1. 运行演示:go run main.go;

  2. 在浏览器中打开http://localhost:8080/。该网页将执行以下操作:

    1. 它向http://0.0.0.0:8081/login1发送请求(目的是验证0.0.0.0的cookie不会与localhost共享;
    2. 它向 http://localhost:8081/login2 发送请求(目的是验证会话 cookie 将在 http://localhost:8080http://localhost:8081 之间共享;
    3. 它向http://localhost:8081/login3发送请求(目的是验证正常的cookie将在http://localhost:8080http://localhost:8081之间共享;
    4. 它导航到 http://localhost:8080/resource 并且服务器将转储请求。表明这个头被发送到服务器:cookie:login2=localhost-session; login3=localhost

注释credentials: 'include' 要求将 access-control-allow-origin 标头设置为确切的来源(这意味着 * 将被拒绝),并且 access- control-allow-credentials 标头设置为 true

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httputil"
)

func setHeader(w http.ResponseWriter, cookieName, cookieValue string, maxAge int) {
    w.Header().Set("Access-Control-Allow-Origin", "http://localhost:8080")
    w.Header().Set("Access-Control-Allow-Credentials", "true")
    http.SetCookie(w, &http.Cookie{
        Name:     cookieName,
        Value:    cookieValue,
        MaxAge:   maxAge,
        HttpOnly: true,
    })
}

func main() {
    muxWeb := http.NewServeMux()
    // serve the HTML page.
    muxWeb.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        _, err := w.Write([]byte(page))
        if err != nil {
            panic(err)
        }
    }))
    // Dump the request to see what cookies is sent to the server.
    muxWeb.Handle("/resource", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        dump, err := httputil.DumpRequest(r, false)
        if err != nil {
            panic(err)
        }
        _, _ = w.Write(dump)
    }))
    web := &http.Server{
        Addr:    ":8080",
        Handler: muxWeb,
    }
    go func() {
        log.Fatal(web.ListenAndServe())
    }()

    muxAPI := http.NewServeMux()
    muxAPI.Handle("/login1", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        setHeader(w, "login1", "0.0.0.0", 1200)
    }))
    muxAPI.Handle("/login2", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        setHeader(w, "login2", "localhost-session", 0)
    }))
    muxAPI.Handle("/login3", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        setHeader(w, "login3", "localhost", 1200)
    }))
    api := &http.Server{
        Addr:    ":8081",
        Handler: muxAPI,
    }
    go func() {
        log.Fatal(api.ListenAndServe())
    }()

    fmt.Println("Open http://localhost:8080/ in the browser")

    select {}
}

var page string = `


  
    
  

`

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

149

2023.12.20

cookie
cookie

Cookie 是一种在用户计算机上存储小型文本文件的技术,用于在用户与网站进行交互时收集和存储有关用户的信息。当用户访问一个网站时,网站会将一个包含特定信息的 Cookie 文件发送到用户的浏览器,浏览器会将该 Cookie 存储在用户的计算机上。之后,当用户再次访问该网站时,浏览器会向服务器发送 Cookie,服务器可以根据 Cookie 中的信息来识别用户、跟踪用户行为等。

6416

2023.06.30

document.cookie获取不到怎么解决
document.cookie获取不到怎么解决

document.cookie获取不到的解决办法:1、浏览器的隐私设置;2、Same-origin policy;3、HTTPOnly Cookie;4、JavaScript代码错误;5、Cookie不存在或过期等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.11.23

阻止所有cookie什么意思
阻止所有cookie什么意思

阻止所有cookie意味着在浏览器中禁止接受和存储网站发送的cookie。阻止所有cookie可能会影响许多网站的使用体验,因为许多网站使用cookie来提供个性化服务、存储用户信息或跟踪用户行为。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

409

2024.02.23

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

307

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

733

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号