लोग गो में प्रमाणीकरण कैसे प्रबंधित कर रहे हैं? [बन्द है]


187

गो में RESTful API और JS फ्रंट-एंड ऐप्स बनाने वालों के लिए, आप प्रमाणीकरण कैसे प्रबंधित कर रहे हैं? क्या आप किसी विशेष पुस्तकालयों या तकनीकों का उपयोग कर रहे हैं?

मैं इस बारे में इतनी कम चर्चा पाकर हैरान हूं। मैं निम्नलिखित बातों को ध्यान में रखता हूं, और अपने स्वयं के कार्यान्वयन को विकसित करने से बचने की कोशिश कर रहा हूं:

ASP.Net में प्रमाणीकरण फॉर्म

क्या हर कोई अपने स्वयं के समाधान को अलग से कोड कर रहा है?


5
प्रमाणीकरण आपके द्वारा किए गए आवेदन के प्रकार पर बहुत हद तक निर्भर करता है। कोई एक आकार-फिट-सभी समाधान नहीं है। इसके अतिरिक्त, इसे हल करना एक कठिन समस्या है। यह संभावना है कि आपको कोई निर्णायक दस्तावेज क्यों नहीं मिलेगा।
jimt

21
हे, त्वरित प्रतिक्रिया के लिए धन्यवाद। समझ में आया, लेकिन अधिकांश भाषाओं और चौखटे प्रमाणीकरण समाधानों के साथ आए हैं जो कि अधिकांश एप्लिकेशन द्वारा साझा की जाने वाली सबसे आम प्रमाणीकरण आवश्यकताओं को कवर करते हैं, और व्यापक सामुदायिक भागीदारी और समर्थन है। मैं मानता हूं कि यह एक कठिन समस्या है। सहकारिता के प्रयासों से उन लोगों को सबसे ज्यादा फायदा नहीं होता है? (यह कोई शिकायत नहीं है, क्योंकि यह खुला स्रोत है, लेकिन एक अवलोकन से अधिक है कि हम सभी पहिया को फिर से
मजबूत

12
@jimt तथ्य यह है कि यह एक कठिन समस्या है, यह हमें और भी महत्वपूर्ण बना देता है कि हम एक नश्वर समाधान के साथ हमें नश्वर आपूर्ति करें कि हम गलत नहीं हो सकते।
tymtam

मैं इस प्रश्न को ऑफ-टॉपिक के रूप में बंद करने के लिए मतदान कर रहा हूं क्योंकि यह एक मतदान प्रश्न है।
फ्लिम्ज़ी

जवाबों:


115

इस सवाल पर एक नज़रिया मिलता है - और एक लोकप्रिय प्रश्न बिल्ला है - इसलिए मुझे पता है कि इस विषय में बहुत अव्यक्त रुचि है, और कई लोग बिल्कुल एक ही बात पूछ रहे हैं और इंटरव्यू पर उत्तर नहीं ढूंढ रहे हैं।

उपलब्ध उपलब्ध अधिकांश जानकारी हाथ की लहराती चीज़ के पाठ के बराबर होती है, जिसे "पाठक के लिए व्यायाम" के रूप में छोड़ दिया जाता है। ;)

हालाँकि, मैं अंत में एक ठोस उदाहरण स्थित हूं, (उदारता से) गोलंग-नट्स के एक सदस्य द्वारा प्रदान की गई मेलिंग सूची:

https://groups.google.com/forum/#!msg/golang-nuts/GE7a_5C5kbA/fdSnH41pOPYJ

यह कस्टम प्रमाणीकरण के लिए एक आधार के रूप में एक सुझाव स्कीमा और सर्वर-साइड कार्यान्वयन प्रदान करता है। क्लाइंट-साइड कोड अभी भी आप पर निर्भर है।

(मुझे आशा है कि पोस्ट के लेखक इसे देखता है: धन्यवाद!)

अंश (और सुधारित):


"मैं निम्नलिखित डिज़ाइन जैसा कुछ सुझाऊंगा:

create table User (
 ID int primary key identity(1,1),
 Username text,
 FullName text,
 PasswordHash text,
 PasswordSalt text,
 IsDisabled bool
)

create table UserSession (
 SessionKey text primary key,
 UserID int not null, -- Could have a hard "references User"
 LoginTime <time type> not null,
 LastSeenTime <time type> not null
)
  • जब कोई उपयोगकर्ता TLS के तहत POST के माध्यम से आपकी साइट पर लॉग इन करता है, तो निर्धारित करें कि क्या पासवर्ड वैध है।
  • फिर एक यादृच्छिक सत्र कुंजी जारी करें, एक सुरक्षित कुकी में 50 या अधिक क्रिप्टो रैंड वर्ण और सामान कहें।
  • उस सत्र कुंजी को उपयोगकर्ता सत्र तालिका में जोड़ें।
  • फिर जब आप उस उपयोगकर्ता को फिर से देखते हैं, तो सबसे पहले UserSession तालिका को देखें कि क्या SessionKey एक मान्य LoginTime और LastSeenTime के साथ वहां है और उपयोगकर्ता हटाया नहीं गया है। आप इसे डिज़ाइन कर सकते हैं ताकि एक टाइमर स्वचालित रूप से उपयोगकर्ता सत्र में पुरानी पंक्तियों को हटा दे। "

8
हम SO पर यहाँ एक स्व-निहित साइट पसंद करते हैं, तो क्या आप यहाँ भी समाधान पोस्ट करना चाहेंगे? बस अगर नियत समय में लिंक बदल जाता है (लिंक रोट और क्या ...) भविष्य के आगंतुकों को इस बारे में खुशी हो सकती है।
टॉप्सकिप

यह एक उचित सवाल है, सम्मानपूर्वक। धन्यवाद। मैंने समाधान शामिल किया है; क्या आपको लगता है कि लेखक का नाम भी शामिल होना चाहिए? (यह सार्वजनिक है, लेकिन मैं किसी भी विकल्प के शिष्टाचार के बारे में आश्चर्यचकित हूं।)
SexxLuthor

मुझे लगता है कि यह अच्छा है। आप इस स्निपेट के "स्वामी" होने का दावा नहीं करते हैं, और मैं यह नहीं देख सकता कि इस स्निपेट के मूल लेखक के लिए यह आवश्यक है कि प्रत्येक कॉपी को एक एट्रिब्यूशन की आवश्यकता हो। (केवल मेरे दो सेंट)।
टॉप्सकिप

35
आपके डेटाबेस में कोई "पासवर्डस्लैट" फ़ील्ड नहीं होना चाहिए, क्योंकि आपको अपने हैशिंग एल्गोरिथ्म के रूप में bcrypt का उपयोग करना चाहिए, जो स्वचालित रूप से एक नमक बनाता है और इसे लौटे हैश में शामिल करता है। इसके अलावा एक निरंतर समय तुलना फ़ंक्शन का उपयोग करें।
0xdabbad00

4
Bcrypt के लिए +1। इसके अलावा, इसके 'एन्क्रिप्शन' और 'ऑथेंटिकेशन' कीज़ के साथ गोरिल्ला सेशन आपको डीबी टेबल का उपयोग किए बिना सत्र की जानकारी को सुरक्षित रखने की अनुमति देगा।
क्रान्तोक

18

एक अन्य संभावित समाधान है , प्रामाणिक रूप से , हाल ही में मेलिंग सूची पर घोषणा की गई है ।

(मैंने इस लाइब्रेरी का उपयोग करने की कोशिश नहीं की है।)

उपयोगकर्ता के साथ वेबपृष्ठ बनाने का सर्वोत्तम तरीका भी देखें ?


14

आप प्रमाणीकरण करने के लिए मिडलवेयर का उपयोग करेंगे।

आप OAuth2 के लिए बेसिक और डाइजेस्ट ऑथेंटिकेशन और गोमन्युथ के लिए गो-http-ऑस्ट्रल की कोशिश कर सकते हैं

लेकिन वास्तव में कैसे प्रमाणित करें यह आपके ऐप पर निर्भर करता है।

प्रमाणीकरण आपके http.Handlers में स्थिति / संदर्भ का परिचय देता है और हाल ही में इसके बारे में कुछ चर्चा हुई है।

प्रसंग समस्या के प्रसिद्ध समाधान गोरिल्ला / संदर्भ और यहाँ वर्णित Google संदर्भ हैं

मैंने गो-ऑन / रैप में वैश्विक स्थिति की आवश्यकता के बिना एक और सामान्य समाधान बनाया जो एक साथ या अन्य दो के बिना इस्तेमाल किया जा सकता है और संदर्भ मुक्त मिडलवेयर के साथ अच्छी तरह से एकीकृत होता है।

wraphttpauth गो-ऑन / रैप के साथ गो-http- ऑर्ट का एकीकरण प्रदान करता है।


शुरुआती लोगों के साथ बहुत सी नई चीजें हैं। मुझे आश्चर्य है कि एक शुरुआत करने वाले को किस तरह की चीज मिलनी चाहिए। go-http-authया gomniauthउन दोनों को?
कैस्पर

यहाँ किसी ने OAuth 1.0 को गोलंग में लागू किया? ConsumerKey और गुप्त आधारित प्रमाणीकरण?
user2888996

मैं oAuth 1.0 को कैसे लागू कर सकता हूं? उपभोक्ता कुंजी और गुप्त का उपयोग करना? कृपया मदद कीजिए। मुझे इसके लिए कोई लाइब्रेरी नहीं मिल रही है।
user2888996

10

2018 में इसका उत्तर देना। मैं JWT (JSON वेब टोकन) का उपयोग करने का सुझाव देता हूं। आपके द्वारा हल किए गए उत्तर में कमियां हैं, यह वह यात्रा है जो उसने (उपयोगकर्ता) और बैक (सर्वर / डीबी) ने की थी। क्या बुरा है अगर उपयोगकर्ता ने लगातार अनुरोध किया है जो कि आवश्यक है, जिसके परिणामस्वरूप / सर्वर और डेटाबेस से फूला हुआ अनुरोध होगा। इस उपयोग को हल करने के लिए JWT जो यूजर एंड में टोकन स्टोर करता है जिसे यूजर द्वारा कभी भी उपयोग किया जा सकता है। टोकन की वैधता कम समय लेने के लिए डेटाबेस और सर्वर प्रोसेसिंग के लिए यात्रा की आवश्यकता नहीं है।


6

कुकीज़ के साथ प्रमाणीकरण को संभालने के लिए एक और खुला स्रोत पैकेज httpauth है

(मेरे द्वारा लिखा गया, वैसे)


2

ईमानदारी से, प्रमाणीकरण विधियों और तकनीकों का एक बहुत कुछ है जो आप अपने आवेदन में माउंट कर सकते हैं और यह अनुप्रयोगों के व्यापार तर्क और आवश्यकताओं पर निर्भर करता है।
उदाहरण के लिए Oauth2, LDAP, स्थानीय प्रमाणीकरण, आदि
मेरा उत्तर मानता है कि आप स्थानीय प्रमाणीकरण की तलाश कर रहे हैं जिसका अर्थ है कि आप अपने आवेदन में उपयोगकर्ता की पहचान का प्रबंधन करते हैं। सर्वर को बाहरी एपीआई के एक सेट को उजागर करना चाहिए जिससे उपयोगकर्ता और व्यवस्थापक खातों का प्रबंधन कर सकें और कैसे वे विश्वसनीय संचार प्राप्त करने के लिए सर्वर की पहचान करना चाहते हैं। आप उपयोगकर्ता की जानकारी रखते हुए एक डीबी टेबल बनाते हुए समाप्त करेंगे। जहां सुरक्षा उद्देश्यों के लिए पासवर्ड हैश किया गया है देखें डेटाबेस में पासवर्ड कैसे स्टोर करें

निम्नलिखित विधियों में से एक के आधार पर उपयोगकर्ताओं को प्रमाणित करने के लिए एप्लिकेशन आवश्यकताओं को मानें:

  • मूल प्रमाणीकरण (उपयोगकर्ता नाम, पासवर्ड):
    यह नियम विधि आधार में एन्कोड किए गए प्राधिकरण हेडर में उपयोगकर्ता क्रेडेंशियल्स सेट पर निर्भर करती है और इसे rfc7617 में परिभाषित किया जाता है , मूल रूप से ऐप प्राप्त होने पर उपयोगकर्ता अपने डीकोड को डीकोड के साथ तुलना करने के लिए पासवर्ड को फिर से प्राधिकरण और फिर से हैश करने का अनुरोध करता है। हैश अगर यह उपयोगकर्ता से प्रमाणित है तो अन्यथा उपयोगकर्ता को 401 स्थिति कोड लौटाएं।

  • सर्टिफिकेट-आधारित प्रमाणीकरण:
    यह प्रमाणिक विधि उपयोगकर्ता को पहचानने के लिए डिजिटल सर्टिफिकेट पर निर्भर करती है, और इसे x509 ऑर्ट के रूप में जाना जाता है, इसलिए जब एप्लिकेशन को उपयोगकर्ता के अनुरोधों को प्राप्त होता है, तो वह ग्राहक के प्रमाण पत्र को पढ़ता है और उसे सत्यापित करता है जो प्रदान किए गए CA रूट प्रमाणपत्र से मेल खाता है। एपीपी को।

  • बियरर टोकन:
    यह सामान्य तरीका अल्पकालिक एक्सेस टोकन पर निर्भर करता है, बियरर टोकन एक क्रिप्टिक स्ट्रिंग है, जो आमतौर पर लॉगिन अनुरोध के जवाब में सर्वर द्वारा उत्पन्न होता है। इसलिए जब एप्लिकेशन उपयोगकर्ता अनुरोधों को प्राप्त करता है तो वह प्राधिकरण को पढ़ता है और उपयोगकर्ता को प्रमाणित करने के लिए टोकन को मान्य करता है।

हालांकि, मैं प्रमाणीकरण पुस्तकालय के लिए गो-संरक्षक की सिफारिश करूंगा जो यह रणनीतियों के रूप में ज्ञात प्रमाणीकरण विधियों के एक विस्तृत सेट के माध्यम से करता है। मूल रूप से गो-गार्जियन मार्गों को माउंट नहीं करता है या किसी विशेष डेटाबेस स्कीमा को नहीं मानता है, जो लचीलेपन को अधिकतम करता है और डेवलपर द्वारा निर्णय लेने की अनुमति देता है।

गो-अभिभावक प्रमाणक की स्थापना करना सीधा है।

यहाँ उपरोक्त विधियों का पूरा उदाहरण दिया गया है।

package main

import (
    "context"
    "crypto/x509"
    "encoding/pem"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "sync"

    "github.com/golang/groupcache/lru"
    "github.com/gorilla/mux"
    "github.com/shaj13/go-guardian/auth"
    "github.com/shaj13/go-guardian/auth/strategies/basic"
    "github.com/shaj13/go-guardian/auth/strategies/bearer"
    gx509 "github.com/shaj13/go-guardian/auth/strategies/x509"
    "github.com/shaj13/go-guardian/store"
)

var authenticator auth.Authenticator
var cache store.Cache

func middleware(next http.Handler) http.HandlerFunc {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Println("Executing Auth Middleware")
        user, err := authenticator.Authenticate(r)
        if err != nil {
            code := http.StatusUnauthorized
            http.Error(w, http.StatusText(code), code)
            return
        }
        log.Printf("User %s Authenticated\n", user.UserName())
        next.ServeHTTP(w, r)
    })
}

func Resource(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Resource!!\n"))
}

func Login(w http.ResponseWriter, r *http.Request) {
    token := "90d64460d14870c08c81352a05dedd3465940a7"
    user := auth.NewDefaultUser("admin", "1", nil, nil)
    cache.Store(token, user, r)
    body := fmt.Sprintf("token: %s \n", token)
    w.Write([]byte(body))
}

func main() {
    opts := x509.VerifyOptions{}
    opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
    opts.Roots = x509.NewCertPool()
    // Read Root Ca Certificate
    opts.Roots.AddCert(readCertificate("<root-ca>"))

    cache = &store.LRU{
        lru.New(100),
        &sync.Mutex{},
    }

    // create strategies
    x509Strategy := gx509.New(opts)
    basicStrategy := basic.New(validateUser, cache)
    tokenStrategy := bearer.New(bearer.NoOpAuthenticate, cache)

    authenticator = auth.New()
    authenticator.EnableStrategy(gx509.StrategyKey, x509Strategy)
    authenticator.EnableStrategy(basic.StrategyKey, basicStrategy)
    authenticator.EnableStrategy(bearer.CachedStrategyKey, tokenStrategy)

    r := mux.NewRouter()
    r.HandleFunc("/resource", middleware(http.HandlerFunc(Resource)))
    r.HandleFunc("/login", middleware(http.HandlerFunc(Login)))

    log.Fatal(http.ListenAndServeTLS(":8080", "<server-cert>", "<server-key>", r))
}

func validateUser(ctx context.Context, r *http.Request, userName, password string) (auth.Info, error) {
    // here connect to db or any other service to fetch user and validate it.
    if userName == "stackoverflow" && password == "stackoverflow" {
        return auth.NewDefaultUser("stackoverflow", "10", nil, nil), nil
    }

    return nil, fmt.Errorf("Invalid credentials")
}

func readCertificate(file string) *x509.Certificate {
    data, err := ioutil.ReadFile(file)

    if err != nil {
        log.Fatalf("error reading %s: %v", file, err)
    }

    p, _ := pem.Decode(data)
    cert, err := x509.ParseCertificate(p.Bytes)
    if err != nil {
        log.Fatalf("error parseing certificate %s: %v", file, err)
    }

    return cert
}

उपयोग:

  • टोकन प्राप्त करें:
curl  -k https://127.0.0.1:8080/login -u stackoverflow:stackoverflow
token: 90d64460d14870c08c81352a05dedd3465940a7
  • टोकन के साथ प्रमाणित करें:
curl  -k https://127.0.0.1:8080/resource -H "Authorization: Bearer 90d64460d14870c08c81352a05dedd3465940a7"

Resource!!
  • एक उपयोगकर्ता क्रेडेंशियल के साथ प्रमाणित करें:
curl  -k https://127.0.0.1:8080/resource -u stackoverflow:stackoverflow

Resource!!
  • उपयोगकर्ता प्रमाणपत्र के साथ प्रमाणित करें:
curl --cert client.pem --key client-key.pem --cacert ca.pem https://127.0.0.1:8080/resource

Resource!!

आप एक साथ कई प्रमाणीकरण विधियों को सक्षम कर सकते हैं। आपको आमतौर पर कम से कम दो तरीकों का उपयोग करना चाहिए


1

Labstack Echo पर एक नज़र डालें - यह RESTful API के लिए प्रमाणीकरण को लपेटता है और अनुप्रयोगों को मिडलवेयर में उपयोग करता है जिन्हें आप विशिष्ट API मार्गों की सुरक्षा के लिए उपयोग कर सकते हैं।

मूल प्रमाणीकरण की स्थापना, उदाहरण के लिए, /adminमार्ग के लिए एक नया सबरटर बनाने के रूप में सीधा है :

e.Group("/admin").Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
    if username == "joe" && password == "secret" {
        return true, nil
    }
    return false, nil
}))

लैबस्टैक के मिडलवेयर ऑथेंटिकेशन ऑप्शन के सभी यहाँ देखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.