User Registration and Login Template using Golang, MongoDB and JWT
Tags: go, jwt, mongodb
Published: 2022-08-12 16:31:53

การลงทะเบียนและเข้าสู่ระบบเป็นส่วนสำคัญของเว็บแอปพลิเคชัน ที่นี่ฉันได้สร้างรหัสเทมเพลตการลงทะเบียนและเข้าสู่ระบบใน 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"`
}
```
นี่คือโครงสร้างผู้ใช้ที่เรียบง่ายซึ่งประกอบด้วยชื่อ นามสกุล อีเมล และรหัสผ่าน ทั้งหมดอยู่ในประเภทข้อมูลสตริง '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)
}
```

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

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

จากนั้นข้อมูลจะถูกเก็บไว้ในฐานข้อมูล 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+`"}`))
}
```

ในฟังก์ชัน 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))

}
```

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