DEV Community

TypeNaN
TypeNaN

Posted on • Edited on

1 1

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

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay