الاستعلام عن قاعدة البيانات للمصادقة الأساسية باستخدام go-http-auth مع martini-go

StackOverflow https://stackoverflow.com//questions/23006639

سؤال

أحاول استخدام 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()

}

تستخدم الوظيفة السرية مستخدمًا مشفرًا "جون".

المصادقة ناجحة عندما أقوم بالتنفيذ

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() معالج عليه وتمرير الوظيفة المشار إليها فقط (انتقل للاحتفاظ بالإشارة إلى "المالك") إلى الملف 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)
   ...
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top