DEV Community

TypeNaN
TypeNaN

Posted on • Edited on

User Registration and Login Template using Golang, MongoDB and JWT

การลงทะเบียนและเข้าสู่ระบบเป็นส่วนสำคัญของเว็บแอปพลิเคชัน ที่นี่ฉันได้สร้างรหัสเทมเพลตการลงทะเบียนและเข้าสู่ระบบใน Golang สำหรับการจัดเก็บข้อมูล ฉันใช้ฐานข้อมูล MongoDB NoSQL สำหรับการกำหนดเส้นทางใน Golang ฉันใช้เราเตอร์ gorilla mux และการเรียก API เพิ่มเติมหลังจากเข้าสู่ระบบจะปลอดภัยด้วย JWT

type User struct{
    FirstName string `json:"firstname" bson:"firstname"` 
    LastName string `json:"lastname" bson:"lastname"` 
    Email string `json:"email" bson:"email"` 
    Password string `json:"password" bson:"password"`
}
Enter fullscreen mode Exit fullscreen mode

นี่คือโครงสร้างผู้ใช้ที่เรียบง่ายซึ่งประกอบด้วยชื่อ นามสกุล อีเมล และรหัสผ่าน ทั้งหมดอยู่ในประเภทข้อมูลสตริง 'json' ใช้สำหรับการแยกวิเคราะห์ข้อมูลสำหรับเซิร์ฟเวอร์ถึงไคลเอนต์และในทางกลับกัน และ 'bson' ใช้สำหรับจัดเก็บข้อมูลใน MongoDB

func userSignup(response http.ResponseWriter, request *http.Request{                       
    response.Header().Set("Content-Type","application/json")             
    var user User json.NewDecoder(request.Body).Decode(&user)  
    user.Password = getHash([]byte(user.Password)) 
    collection := client.Database("GODB").Collection("user") 
    ctx,_ := context.WithTimeout(context.Background(),      
             10*time.Second) 
    result,err := collection.InsertOne(ctx,user)
    if err!=nil{     
        response.WriteHeader(http.StatusInternalServerError)    
        response.Write([]byte(`{"message":"`+err.Error()+`"}`))    
        return
    }    
    json.NewEncoder(response).Encode(result)
}
Enter fullscreen mode Exit fullscreen mode

ด้านบนฟังก์ชัน userSignup กำลังทำส่วนการลงทะเบียนผู้ใช้ ข้อมูล json ของเนื้อหาการตอบสนองที่มาจากเบราว์เซอร์ไคลเอ็นต์จะถูกถอดรหัสในโครงสร้างผู้ใช้ รหัสผ่านจะถูกแฮชก่อนจัดเก็บไว้ในฐานข้อมูลโดยมีข้อมูลโค้ดด้านล่าง สำหรับการมีรหัสผ่าน ฉันใช้ bcrypt

func getHash(pwd []byte) string {        
    hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)          
    if err != nil {
       log.Println(err)
    }
    return string(hash)
}
Enter fullscreen mode Exit fullscreen mode

จากนั้นข้อมูลจะถูกเก็บไว้ในฐานข้อมูล MongoDB ด้วยฟังก์ชัน InsertOne ข้อมูลถูกเก็บไว้ในฐานข้อมูล 'GODB' ในคอลเล็กชัน 'ผู้ใช้' ฐานข้อมูลและชื่อคอลเลกชันสามารถให้บริการได้จากไฟล์การกำหนดค่า จากนั้นผลลัพธ์ (Insert data Object Id) จะถูกเข้ารหัสลงใน json และเซิร์ฟเวอร์ตอบสนองเป็นสัญญาณของการลงทะเบียนที่สำเร็จ

func userLogin(response http.ResponseWriter, request *http.Request){   
    response.Header().Set("Content-Type","application/json")  
    var user User 
    var dbUser User  
    json.NewDecoder(request.Body).Decode(&user)  
    collection:= client.Database("GODB").Collection("user")  
    ctx,_ :=context.WithTimeout(context.Background(),10*time.Second)        err:=collection.FindOne(ctx,bson.M{"email":user.Email}).Decode(&dbUser)
    if err!=nil{      
       response.WriteHeader(http.StatusInternalServerError)     
       response.Write([]byte(`{"message":"`+err.Error()+`"}`))    
       return
    }
    userPass:= []byte(user.Password)
    dbPass:= []byte(dbUser.Password)
    passErr:= bcrypt.CompareHashAndPassword(dbPass, userPass)
    if passErr != nil{
       log.Println(passErr)    
       response.Write([]byte(`{"response":"Wrong Password!"}`))    
       return
    }
    jwtToken, err := GenerateJWT()
    if err != nil{   
    response.WriteHeader(http.StatusInternalServerError)  
    response.Write([]byte(`{"message":"`+err.Error()+`"}`))
    return
    }
    response.Write([]byte(`{"token":"`+jwtToken+`"}`))
}
Enter fullscreen mode Exit fullscreen mode

ในฟังก์ชัน userLogin ด้านบน ขั้นแรกฉันได้ถอดรหัสข้อมูลผู้ใช้ (อีเมลและรหัสผ่าน) ที่มาจากไคลเอนต์ไปยังโครงสร้างผู้ใช้ จากนั้นฉันได้ผ่านฐานข้อมูลเพื่อตัดสินใจว่าผู้ใช้ปัจจุบันมีอยู่ในฐานข้อมูลหรือไม่ทางอีเมล หากอีเมลตรงกับข้อมูลใด ๆ ฉันจะเปรียบเทียบผู้ใช้ที่ให้รหัสผ่านและรหัสผ่านที่จัดเก็บไว้ในฐานข้อมูล หากรหัสผ่านตรงกัน โทเค็น jwt จะถูกส่งตอบกลับเพื่อเป็นสัญญาณของการเข้าสู่ระบบที่สำเร็จ

นี่คือรหัสเต็ม:

package main

import (
    "context"
    "time"
    "log"
    "net/http"
    "github.com/gorilla/mux"
    "encoding/json"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/bson"
    "golang.org/x/crypto/bcrypt"
    "github.com/dgrijalva/jwt-go"
)


var SECRET_KEY = []byte("gosecretkey")

type User struct{
    FirstName string `json:"firstname" bson:"firstname"`
    LastName string `json:"lastname" bson:"lastname"`
    Email string `json:"email" bson:"email"`
    Password string `json:"password" bson:"password"`
}

var client *mongo.Client

func getHash(pwd []byte) string {
    hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)
    if err != nil {
        log.Println(err)
    }
    return string(hash)
}

func GenerateJWT()(string,error){
    token:= jwt.New(jwt.SigningMethodHS256)
    tokenString, err :=  token.SignedString(SECRET_KEY)
    if err !=nil{
        log.Println("Error in JWT token generation")
        return "",err
    }
    return tokenString, nil
}

func userSignup(response http.ResponseWriter, request *http.Request){
    response.Header().Set("Content-Type","application/json")
    var user User
    json.NewDecoder(request.Body).Decode(&user)
    user.Password = getHash([]byte(user.Password))
    collection := client.Database("GODB").Collection("user")
    ctx,_ := context.WithTimeout(context.Background(), 10*time.Second)
    result,_ := collection.InsertOne(ctx,user)
    json.NewEncoder(response).Encode(result)
}


func userLogin(response http.ResponseWriter, request *http.Request){
  response.Header().Set("Content-Type","application/json")
  var user User
  var dbUser User
  json.NewDecoder(request.Body).Decode(&user)
  collection:= client.Database("GODB").Collection("user")
  ctx,_ := context.WithTimeout(context.Background(),10*time.Second)
  err:= collection.FindOne(ctx, bson.M{"email":user.Email}).Decode(&dbUser)

  if err!=nil{
      response.WriteHeader(http.StatusInternalServerError)
      response.Write([]byte(`{"message":"`+err.Error()+`"}`))
      return
  }
  userPass:= []byte(user.Password)
  dbPass:= []byte(dbUser.Password)

  passErr:= bcrypt.CompareHashAndPassword(dbPass, userPass)

  if passErr != nil{
      log.Println(passErr)
      response.Write([]byte(`{"response":"Wrong Password!"}`))
      return
  }
  jwtToken, err := GenerateJWT()
  if err != nil{
    response.WriteHeader(http.StatusInternalServerError)
    response.Write([]byte(`{"message":"`+err.Error()+`"}`))
    return
  }
  response.Write([]byte(`{"token":"`+jwtToken+`"}`))

}


func main(){
    log.Println("Starting the application")

    router:= mux.NewRouter()
    ctx,_ := context.WithTimeout(context.Background(), 10*time.Second)
    client,_= mongo.Connect(ctx,options.Client().ApplyURI("mongodb://localhost:27017"))

    router.HandleFunc("/api/user/login",userLogin).Methods("POST")
    router.HandleFunc("/api/user/signup",userSignup).Methods("POST")

    log.Fatal(http.ListenAndServe(":8080", router))

}
Enter fullscreen mode Exit fullscreen mode

original post :
https://medium.com/@pkbhowmick007/user-registration-and-login-template-using-golang-mongodb-and-jwt-d85f09f1295e

Top comments (0)