duanpi2033 2016-03-31 23:43
浏览 31
已采纳

具有标题的http.Redirect()

I have a web page that emulates authorizing API access. The user enters an API url and an authorization key (let's say "true" or "false"). On the Go side, there's a handler function for this path which reads the form and generates a token based on the authorization key.
Ideally, I'd like to save the token as a header and redirect the request to the proper handler based on the API url entered. However, when I use http.Redirect(), my header does not get sent as part of the request.

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
    }
}

There may be several API urls with different paths, but my thought process has the token being written as a header in that same handler function every time. I'm designing it this way because the API url may eventually redirect to different domains, so I'd like to keep it separate from reading the form.
Google tells me to use Client.CheckRedirect somehow, but I'm not sure how to implement it in my handler functions. How can I redirect while keeping my headers? Thank you!

  • 写回答

1条回答 默认 最新

  • duanniubeng2265 2016-04-01 00:05
    关注

    It's because the HTTP standard does not pass through HTTP headers on an 302/301 directive. It's not a GoLang issue, it's an HTTP 1.0 (and 2.0?) standards issue.

    You are thinking correctly, using the POST-REDIRECT-GET pattern for common FORM postings to your web app (it prevents the old browser-refresh "Do you want to resubmit the form?" annoying error).

    And btw, yes that's the correct status code. Note that http.StatusFound is a 302 code, which indicates it is a temp move. Never use the 301 Permanent Move status for a Postback redirect.

    There are some common work-arounds though.

    Sessions

    Several server-side languages have Sessions that store the value on the backend.

    • store the value/result in a variable tied to the user's session on the backend DB
    • redirect
    • read the session value on the new page load

    ASP.NET is one such backend language. ASP.NET sessions ties a session to a user by 1) creating a session upon the first hit to the server and 2) taking the session_id and setting a brower-session (only valid while the browser session is active, close the browser and the cookie is removed). That way on every "request" to the server, the cookie is read for the sessions_id, it is grabbed from your data store, and populates the Session user var.

    Personally, I've never duplicated this functionality in Go. But, one could.

    Note, this really the only way to complete secure your "secret" token, if it is a secret. Then again, one could steal the session_id and impersonate the request. Then again, one could implement a 4-way browser fingerprint to help limit impersonation. Then again, if one is able to sniff the cookie that has the session_id, then they would be able to sniff all the parameters of the fingerprint method (except IP!).

    Temp Cookie

    My personal favorite is storing the value in a tmp browser-session cookie with an expiration of Now() -1 (meaning, it will expire immediately). This allows you to read the cookie only 1 time, on the redirect's web request, before the browser expires it after that request.

    It's a trick I picked up from ASP.NET MVC, and I enforced on all of my controllers (by disabling Sessions and writing my own temp cookie handler).

    Just note that it will not be private/secret: it will sent over your connection. Even if HTTPS, it will still be seen in the browser's add-ons, cookie handlers, etc. Yes, you could "encrypt" the value,a nd decrypt it back on the server side for security: but then, it's only as strong as your encryption (and bloats your request/response sizes).

    Good 'ol Querystring Parameter

    Can't beat:

    /my/url?token=23462345345345
    

    Since you were trying to put it into the header, it isn't a secret anyways.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥40 如果update 一个列名为参数的value
  • ¥15 基于51单片机的水位检测系统设计中LCD1602一直不显示
  • ¥15 OCS2安装出现问题,请大家给点意见
  • ¥15 ros小车启动launch文件报错
  • ¥15 vs2015到期想登陆但是登陆不上
  • ¥15 IPQ5018制作烧录固件,boot运行失败(操作系统-linux)(相关搜索:操作系统)(相关搜索:操作系统)
  • ¥20 icefall在librispeech基础上加入个人数据集
  • ¥30 keepalive高可用故障运维配置询问
  • ¥15 求帮助!国家电网内网u盘突然识别不出来了。
  • ¥15 matlab语音变速变调同时实现