golang 与 fastcgi 如何阅读 REMOTE_USER

golang with fastcgi how to read REMOTE_USER

简而言之:如何使用 fastcgi 在 golang 上读取 CGI var REMOTE_USER?

长: 我正在尝试编写一个程序,以便在套接字上使用 fcgi 在 httpd 后面工作。 httpd 执行 ssl 终止并提供基本身份验证。我需要阅读 $REMOTE_USER,但我不能在 golang 中阅读,而我可以在 perl 中阅读。

我的代码基于this fcgi example。我试试

func homeView(w http.ResponseWriter, r *http.Request) {     
    user, pass, authok := r.BasicAuth()

但是 authok 始终为 false,user 和 pass 仍然为空,尽管我确信授权(由 httpd 完成)是正确的。为了消除其他错误,我在perl中完成了:

my $socket = FCGI::OpenSocket("/run/fcgi-check.sock", 5);
my $q = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket);

while ($q->Accept() >= 0) {
    my $c = CGI::Simple->new;
    my $user_id      = $c->remote_user(); 

它在 perl 中运行良好。

为了调试,我打印了 r.Header 的输出,我得到:

map[Authorization:[]

go see 的 header 没有任何授权信息,我说得对吗?但它在 perl 中确实如此。

这是一个完整但最小的 golang 代码示例,它演示了这个问题(在 OpenBSD 5.8 上使用 go 版本 go1.4.2 openbsd/amd64 和在 httpd.conf 中使用 'authenticate "/" with restricted_users' 的 OpenBSDs httpd。

package main

import (
        "github.com/gorilla/mux"
        "io"
        "log"
        "fmt"
        "net"
        "net/http"
        "net/http/fcgi"
)


func homeView(w http.ResponseWriter, r *http.Request) {
        headers := w.Header()
        headers.Add("Content-Type", "text/html")
        headers.Add("Cache-Control", "no-cache, no-store, must-revalidate")
        headers.Add("Pragma", "no-cache")
        headers.Add("Expires", "0")
        r.ParseForm()

        user, pass, authok := r.BasicAuth()

        if authok {
                io.WriteString(w, fmt.Sprintln("Auth OK"))
                io.WriteString(w, fmt.Sprintln("user is: "+user+", pass is: "+pass))
        } else {
                io.WriteString(w, fmt.Sprintln("Auth NOT OK"))
        }
}

func main() {

        r := mux.NewRouter()
        r.HandleFunc("/check/", homeView)

    var err error
        listener, err := net.Listen("unix", "/run/fcgi-check.sock")
        if err != nil {
                log.Fatal(err)
        }
        defer listener.Close()

        err = fcgi.Serve(listener, r)
        if err != nil { log.Fatal(err)}
}

不胜感激!

提前致谢! T.

虽然 @JimB 是正确的,您的方法是错误的,但我会按照说明回答问题。

net/http/fcgi 包使用 net/http/cgi 的机制来填充 http.Request 的实例——传递给你的处理程序——使用 "parameters" (key/value 对)由网络服务器在 FastCGI 会话(调用)期间提交。 这是完成 here.

现在,如果您要检查 the relevant bit of the net/http/cgi code, you'll see that the variables which are not mapped to specific dedicated fields of http.Request get converted to HTTP "headers"

这意味着,您的代码应该能够使用类似

的方式访问您需要的变量
ruser := r.Header.Get("Remote-User")

2015-12-02 更新: @JimB 和 OP 进行的研究表明显然无法读取 REMOTE_USER 下的变量快速CGI。抱歉噪音。

简单的回答(从 go 版本 1.4.2 开始)是 go 目前不支持 CGI 变量的传输 REMOTE_USER。

fcgi 包的 core change 正在审核中,即将合并。如果它不再与您相关,希望它对其他人有用。

Go 1.9 将公开 cgi 环境变量。如这张已关闭的票证所示:

https://go-review.googlesource.com/c/40012