【问题标题】:How to serve static files with basic authentication?如何使用基本身份验证提供静态文件?
【发布时间】:2014-10-22 12:15:54
【问题描述】:

我无法使用github.com/abbot/go-http-authhttp.FileServer 进行基本身份验证。

package main

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

    "github.com/abbot/go-http-auth"
)

func Secret(user, realm string) string {
    users := map[string]string{
        "john": "$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1", //hello
    }

    if a, ok := users[user]; ok {
        return a
    }
    return ""
}

func doRoot(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "<h1>static file server</h1><p><a href='./static'>folder</p>")
}

func handleFileServer(w http.ResponseWriter, r *http.Request) {
    fs := http.FileServer(http.Dir("static"))
    http.StripPrefix("/static/", fs)
}

func main() {

    authenticator := auth.NewBasicAuthenticator("localhost", Secret)

    // how to secure the FileServer with basic authentication??
    // fs := http.FileServer(http.Dir("static"))
    // http.Handle("/static/", http.StripPrefix("/static/", fs))

    http.HandleFunc("/static/", auth.JustCheck(authenticator, handleFileServer))

    http.HandleFunc("/", auth.JustCheck(authenticator, doRoot))

    log.Println(`Listening... http://localhost:3000
 folder is ./static
 authentication in map users`)
    http.ListenAndServe(":3001", nil)
}

代码:

fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))

main() 中工作无需身份验证,但不能与auth.JustCheck 一起使用。我尝试使用handleFileServer 函数,但没有显示任何内容。有什么诀窍?

【问题讨论】:

  • 你试过http.HandleFunc("/static/", auth.JustCheck(authenticator, http.StripPrefix(http.FileServer(http.Dir("static"))).ServeHTTP)吗?

标签: go basic-authentication fileserver


【解决方案1】:

需要返回StripPrefix的ServeHTTP方法,例如:

func handleFileServer(dir, prefix string) http.HandlerFunc {
    fs := http.FileServer(http.Dir(dir))
    realHandler := http.StripPrefix(prefix, fs).ServeHTTP
    return func(w http.ResponseWriter, req *http.Request) {
        log.Println(req.URL)
        realHandler(w, req)
    }
}

func main()
    //....
    http.HandleFunc("/static/", auth.JustCheck(authenticator, handleFileServer("/tmp", "/static/")))
    //....
}

【讨论】:

  • 非常感谢您,特别感谢您将您的评论提炼为工作代码。我现在应该找到一种方法来消除编写两次“静态”url 前缀的需要。
  • 但是,如何在函数 doRoot 中访问参数(w http.ResponseWriter,r *http.Request)?我被它困住了。