golang-cgi+apache登录会话管理



我是golang的新手。我想使用golang作为我的apache服务器的cgi。我不想以监听器/服务器的身份运行我的golang程序。我为每个操作编写.go文件,如login.go、logout.go、welcome.go,并将它们编译成单独的exe。我将ex重命名为cgi,并将它们放在apache的cgi-bin文件夹中,然后从我的html文件发布到cgi-bin文件中。我希望我的go lang通过apache服务。

这是我的简单html表单

<html>
<head><title>Go Test</title></head>
<body>
<form action='cgi-bin/login.cgi' method='post'>
username : <input name='username' value='vimal'><br>
password : <input name='password' value='hello'><br>
<input type='submit' value='submit'>
</form>
</body>
</html>

这是我的golang登录源。我编译到login.exe中,将其重命名为login.cgi,并将其放在apache的cgibin文件夹中。

package main
import (
"net/http/cgi"
"net/http"
"fmt"
)
var (
// key must be 16, 24 or 32 bytes long (AES-128, AES-192 or AES-256)
// key = []byte("super-secret-key")
key = uuid.NewV4().String()
store = sessions.NewCookieStore(key)
)
func errorResponse(code int, msg string) {
fmt.Printf("Status:%d %srn", code, msg)
fmt.Printf("Content-Type: text/plainrn")
fmt.Printf("rn")
fmt.Printf("%srn", msg)
}
func main() {
var req *http.Request
var w *http.ResponseWriter
var err error
req, err = cgi.Request()
if err != nil {
errorResponse(500, "cannot get cgi request" + err.Error())
return
}
if err := req.ParseForm(); err != nil {
errorResponse(500, "cannot get cgi request" + err.Error())
}
username := req.FormValue("username")
password := req.FormValue("password")
//create session
//store session variables like user id, user name etc., that can be accessed through other .cgi files like welcome.cgi 
// Use req to handle request
fmt.Printf("Content-type: text/htmlnn")
fmt.Printf("<!DOCTYPE html>n")
fmt.Printf("<p>username: %sn",username)
fmt.Printf("<p>password: %sn",password)
fmt.Printf("req=%vrn", req)
}

我需要帮助创建会话并存储会话变量,如用户id、用户名等。,如果我的另一个golang-cgi文件welcome.cgi被调用,它应该能够访问会话变量,如用户id、名称并打印它们

请向我提供完整的代码。我是新来的戈兰。我不想用我的高尔夫当服务器。我只想制作一些小的cgi页面。感谢

您可以使用普通的处理程序,就像互联网上几个例子中使用的处理程序一样,这样您就不需要使用一系列fmt.Printf来向CGI服务器发送数据。我发现一种简单的工作方式是使用cgi.Serve函数,它可以与http.HandlerFunc一起使用。使用http.HandlerFunchttp.Handler将允许您在go中使用任何使用http.ResponseWriterhttp.Request的会话管理器实现。但是,请注意,您不应该使用程序内部随机生成的密钥初始化存储,而且,如果您使用数据库后端,您将无法直接从go使用连接轮询,因为您的程序主函数将在每个请求上执行,并且它应该在每次调用时打开关闭的连接。

下面是一个使用上述方法的简单示例:

package main
import (
"encoding/hex"
"fmt"
"io"
"net/http"
"net/http/cgi"
"os"
"github.com/gorilla/sessions"
)
func main() {
// Use Serve function with an anonymous function, you can also  use instances
// of http.Handler. The function does not need to be an anonymous function, it
// just has to match the HandlerFunc signature
err := cgi.Serve(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Get the session auth key from a trusted source,
// in this example an env var is used. You can use any mechanism you want
// so long that you don't generate it from within this program
key, _ := hex.DecodeString(os.Getenv("SESSION_AUTH_KEY"))
store := sessions.NewCookieStore(key)
// Get a session from the store if any
sess, err := store.Get(r, "mysess")
if err != nil {
io.WriteString(rw, fmt.Sprintf("error reading cookies: %v", err))
return
}
if sess.IsNew {
sess.Values["val"] = 1
//Save your store before writing anything to the client
if err := sess.Save(r, rw); err != nil {
io.WriteString(rw, "error writing sesion")
} else {
io.WriteString(rw, "new session")
}
return
}
//Write session values to validate that your session is working
io.WriteString(rw, "Values:")
for name, value := range sess.Values {
io.WriteString(rw, fmt.Sprintf("name: %s, val: %v", name, value))
}
}))
if err != nil {
fmt.Fprintf(os.Stderr, "Error :%v", err)
}
}

最新更新