Golang:带标题的http.Redirect()

时间:2016-03-31 23:43:28

标签: http go

我有一个模仿授权API访问权限的网页。用户输入API URL和授权密钥(假设为“true”或“false”)。在Go方面,这个路径有一个处理函数,它读取表单并根据授权密钥生成一个令牌 理想情况下,我想将令牌保存为标头,并根据输入的API网址将请求重定向到正确的处理程序。但是,当我使用http.Redirect()时,我的标头不会作为请求的一部分发送。

func createTokenHandler(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    path := r.FormValue("path")
    auth := r.FormValue("auth") // let's say "true" or "false"
    w.Header().Set("auth", auth)
    http.Redirect(w, r, path, http.StatusFound) // is this the correct http code?
}

// path redirects to this handler
func otherPathHandler(w http.ResponseWriter, r *http.Request) {
    // these were necessary for cross-domain requests to work with custom header, keeping them
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "auth")
    auth = r.Header.Get("auth")
    if auth == "true" {
        w.Write([]byte("Validated, here's the API response."))
        // continue
    }
}

可能有几个具有不同路径的API网址,但我的思维过程每次都将令牌写入同一个处理函数中的标头。我正是这样设计的,因为API网址最终可能会重定向到不同的域名,因此我想将其与阅读表单分开。
Google告诉我以某种方式使用Client.CheckRedirect,但我不确定如何在我的处理程序函数中实现它。如何在保留标题的同时重定向?谢谢!

1 个答案:

答案 0 :(得分:7)

这是因为HTTP标准没有通过302/301指令上的HTTP标头。它不是GoLang问题,它是HTTP 1.0(和2.0?)标准问题。

您正在思考,使用POST-REDIRECT-GET模式将常见的FORM发布到您的Web应用程序(它会阻止旧的浏览器刷新"您要重新提交表单吗?"恼人的错误)。

顺便说一句,是的,这是正确的状态代码。请注意,http.StatusFound是一个302代码,表示它是临时移动。切勿将301永久移动状态用于回发重定向。

虽然有一些常见的解决方法。

会话

有几种服务器端语言Sessions将值存储在后端。

  • 将值/结果存储在与后端数据库上的用户会话相关联的变量中
  • 重定向
  • 在新页面加载
  • 上读取会话值

ASP.NET就是这样一种后端语言。 ASP.NET会话通过以下方式将会话与用户联系起来:1)在第一次点击服务器时创建会话; 2)获取session_id并设置brower-session(仅在浏览器会话处于活动状态时有效,关闭浏览器和cookie被删除)。这样每个"请求"在服务器上,为sessions_id读取cookie,从数据存储中获取cookie,并填充Session用户var。

就个人而言,我从来没有在Go中复制过这个功能。但是,有人可以。

请注意,这真的是完成保护您的秘密"令牌,如果它是一个秘密。然后,人们可以窃取session_id并冒充请求。然后,人们可以实施4-way browser fingerprint来帮助限制模仿。然后,如果一个人能够嗅探具有session_id的cookie,那么他们就能够嗅探指纹方法的所有参数(除了IP!)。

Temp Cookie

我个人最喜欢的是将值存储在tmp浏览器会话cookie中,其值为Now() -1(意味着它将立即过期)。这允许您在重定向的Web请求之前仅在浏览器在该请求之后使其到期之前读取cookie一次。

这是我从ASP.NET MVC中获取的一个技巧,我在所有控制器上强制执行(通过禁用Sessions并编写我自己的临时cookie处理程序)。

请注意,它不会是私密/秘密:它会通过您的连接发送。即使是HTTPS,它仍然可以在浏览器的附加组件,cookie处理程序等中看到。是的,你可以加密"该值,并在服务器端将其解密以确保安全性:但是,它只会像您的加密一样强大(并且会增加您的请求/响应大小)。

Good' ol Querystring Parameter

无法击败:

/my/url?token=23462345345345

由于你试图将它放入标题中,所以它无论如何都不是秘密。