使用 go-http-auth 和 martini-go 查询数据库的基本身份验证
-
21-12-2019 - |
题
我正在尝试将 go-http-auth 与 martini-go 一起使用。在此处给出的示例中 - https://github.com/abbot/go-http-auth
package main
import (
auth "github.com/abbot/go-http-auth"
"fmt"
"net/http"
)
func Secret(user, realm string) string {
if user == "john" {
// password is "hello"
return "$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"
}
return ""
}
func handle(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
fmt.Fprintf(w, "<html><body><h1>Hello, %s!</h1></body></html>", r.Username)
}
func main() {
db, err := sql.Open("postgres", "postgres://blabla:blabla@localhost/my_db")
authenticator := auth.NewBasicAuthenticator("example.com", Secret)
m := martini.Classic()
m.Map(db)
m.Get("/users", authenticator.Wrap(MyUserHandler))
m.Run()
}
Secret 函数使用硬编码用户“john”。
当我执行时认证成功
curl --user john:hello localhost:3000/users
显然,这是一个带有硬编码用户名和密码的简单示例。
我现在正在改变 Secret
函数到此
func Secret(user, realm string) string {
fmt.Println("Executing Secret")
var db *sql.DB
var (
username string
password string
)
err := db.QueryRow("select username, password from users where username = ?", user).Scan(&username, &password)
if err == sql.ErrNoRows {
return ""
}
if err != nil {
log.Fatal(err)
}
//if user == "john" {
//// password is "hello"
//return "$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"
//}
//return ""
return ""
}
但它失败了 PANIC: runtime error: invalid memory address or nil pointer dereference.
这显然是因为我正在尝试实例化 var db *sql.DB
在里面 Secret
功能。我无法通过 db *sql.DB
进入 Secret
函数要么因为 auth.BasicNewAuthentication
正在期待一个 Secret
符合的论点 type func (string, string) string
.
如何正确实现我的数据库查询并返回密码进行比较?
解决方案
您可以使用一个简单的闭包将对数据库的引用传递给验证器函数:
authenticator := auth.NewBasicAuthenticator("example.com", func(user, realm string) string {
return Secret(db, user, realm)
})
...然后改变你的 Secret
接受数据库作为第一个参数:
func Secret(db *sql.DB, user, realm string) string {
// do your db lookup here…
}
其他提示
阿提拉斯答案的替代方法。您可以定义一个结构体,定义 Secret()
处理程序并仅将引用的函数(go 保留对“所有者”的引用)传递到 authhandler
.
type SecretDb struct {
db *DB
}
func (db *SecretDb) Secret(user, realm string) string {
// .. use db.db here
}
func main() {
secretdb = SecretDb{db}
...
auth.NewBasicAuthenticator("example.com", secretdb.Secret)
...
}
不隶属于 StackOverflow