douqin7086
douqin7086
2015-11-30 20:02

与fastcgi的golang如何阅读REMOTE_USER

已采纳

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.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

4条回答

  • doutao1282 doutao1282 6年前

    The simple answer (as of go version 1.4.2) is that go currently does not support the transfer of CGI variable REMOTE_USER.

    点赞 评论 复制链接分享
  • dsfsdf7852 dsfsdf7852 4年前

    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.

    点赞 评论 复制链接分享
  • doushu8260 doushu8260 6年前

    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, your code should be able to access the variable you need using something like

    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.

    点赞 评论 复制链接分享
  • duanbei3704 duanbei3704 4年前

    Go 1.9 will expose cgi environment variables. As seen in this closed ticket:

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

    点赞 评论 复制链接分享

相关推荐