Frage

Ich versuche, go-http-auth mit martini-go zu verwenden.In dem hier gegebenen Beispiel - 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()

}

Die Secret-Funktion verwendet einen fest codierten Benutzer „john“.

Die Authentifizierung ist erfolgreich, wenn ich sie ausführe

curl --user john:hello localhost:3000/users

Dies ist offensichtlich ein triviales Beispiel mit fest codiertem Benutzernamen und Passwort.

Ich ändere jetzt das Secret Funktion dazu

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 ""

}

Aber es scheitert mit PANIC: runtime error: invalid memory address or nil pointer dereference. Das liegt offensichtlich daran, dass ich versuche zu instanziieren var db *sql.DB im Secret Funktion.Ich kann nicht bestehen db *sql.DB in die Secret Funktion entweder weil auth.BasicNewAuthentication erwartet einen Secret Argument, das entspricht type func (string, string) string.

Wie kann ich meine Datenbankabfrage korrekt umsetzen und das Passwort zum Vergleich zurückgeben?

War es hilfreich?

Lösung

Sie können einen einfachen Abschluss verwenden, um einen Verweis auf Ihre Datenbank an die Authentifikatorfunktion zu übergeben:

authenticator := auth.NewBasicAuthenticator("example.com", func(user, realm string) string {
    return Secret(db, user, realm)
})

…und dann ändern Sie Ihre Secret um die Datenbank als erstes Argument zu akzeptieren:

func Secret(db *sql.DB, user, realm string) string {
    // do your db lookup here…
}

Andere Tipps

Alternativer Ansatz zur Antwort von Attilas.Sie können eine Struktur definieren, die definieren Secret() Handler darauf und übergeben Sie nur die referenzierte Funktion (go behält den Verweis auf den „Eigentümer“) an den 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)
   ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top