英文:
golang with fastcgi how to read REMOTE_USER
问题
如何在使用FastCGI的Golang中读取CGI变量REMOTE_USER?
我正在尝试编写一个在httpd后面使用fcgi通过套接字工作的Go程序。httpd执行SSL终止并提供基本身份验证。我需要读取$REMOTE_USER,但是在Golang中我无法实现,而在Perl中可以。
我的代码基于这个fcgi示例。我尝试了以下代码:
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看到的标头不包含任何关于授权的信息?但是在Perl中有。
下面是一个完整但最小化的Golang代码示例,演示了这个问题(在OpenBSD 5.8上使用go版本go1.4.2 openbsd/amd64和OpenBSD的httpd,httpd.conf中有'authenticate "/" with restricted_users'):
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.
英文:
Short: How can I read the CGI var REMOTE_USER on golang using fastcgi?
Long:
I'm trying to write a program in go to work behind a httpd using fcgi over a socket. The httpd does the ssl termination and provides basic auth. I need to read $REMOTE_USER, but I cannot in golang, while I can in perl.
My code is based on this fcgi example. I try
func homeView(w http.ResponseWriter, r *http.Request) {
user, pass, authok := r.BasicAuth()
But authok is always false, user and pass remain empty, although I know for sure that the authorization (done by httpd) was OK. To eliminate other errors, I have done it in 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();
and it works fine in perl.
To debug, I printed the output of r.Header and I got:
map[Authorization:[]
Am I right that the header that go sees does no hold any information about any authorization? But it does in perl.
Here is a full but minimal golang code example that demonstrates the problem (on OpenBSD 5.8 with go version go1.4.2 openbsd/amd64 and OpenBSDs httpd with 'authenticate "/" with restricted_users' in httpd.conf.
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)}
}
Help will be appreciated!
Thanks in advance!
T.
答案1
得分: 2
Go 1.9将公开CGI环境变量。如在此关闭的票证中所见:
https://go-review.googlesource.com/c/40012
英文:
Go 1.9 will expose cgi environment variables. As seen in this closed ticket:
答案2
得分: 1
虽然@JimB
正确指出你在方法上是错误的,但我会按照问题的陈述来回答。
net/http/fcgi
包使用net/http/cgi
的机制来填充一个http.Request
实例,该实例会传递给你的处理程序,在FastCGI会话(调用)期间由Web服务器提交的“参数”(键/值对)。
这是在这里完成的。
现在,如果你检查一下net/http/cgi
代码的相关部分,你会发现那些没有映射到http.Request
特定字段的变量会被转换为HTTP“头部”。
这意味着,你的代码应该能够使用类似下面的方式访问你需要的变量:
ruser := r.Header.Get("Remote-User")
更新于2015-12-02: @JimB
和OP进行的研究表明,在FastCGI下似乎没有办法读取REMOTE_USER
变量。对于造成的困扰,我表示抱歉。
英文:
While @JimB
is correct on that you're wrong in your approach, I'll answer the question as stated.
The net/http/fcgi
package uses the machinery of net/http/cgi
to populate an instance of http.Request
—which is passed to your handler—with "parameters" (key/value pairs) submitted by the webserver during the FastCGI session (call).
This is done here.
Now if you'll inspect 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".
This means, <s>your code should be able to access the variable you need using something like</s>
ruser := r.Header.Get("Remote-User")
Update 2015-12-02: the reseach performed by @JimB
and the OP showed that there's apparently no way to read the REMOTE_USER
variable under FastCGI. Sorry for the noise.
答案3
得分: 1
简单的答案是,截至Go版本1.4.2,Go目前不支持传输CGI变量REMOTE_USER。
英文:
The simple answer (as of go version 1.4.2) is that go currently does not support the transfer of CGI variable REMOTE_USER.
答案4
得分: 1
这个对 fcgi 包的核心更改正在审核中,即将合并。如果对你不再相关,希望对其他人有用。
英文:
This core change to the fcgi package is in review and is close to being merged. If it's no longer relevant to you, hopefully it will be useful to others.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论