Hôm nay mình sẽ code và chạy thử một ví dụ mẫu về xác thực sử dụng JWT (JSON Web Token).
Điều kiện ở đây là đã có đầy đủ server database để kết nối và POSTMAN để tạo request.
Các bước chạy thử JWT.
Bước 1:
Đầu tiên đăng ký user bằng cách gọi request sau và truyền dữ liệu JSON:
POST localhost:8080/register
Xem kết quả trả ra trên POSTMAN
Code của đoạn đăng ký này:
func Register(ctx *fiber.Ctx) error {
var data map[string]string
if err := ctx.BodyParser(&data); err != nil {
log.Print(err)
return err
}
if data["password"] != data["passwordconfirm"] { //Kiểm tra password có match ko
ctx.Status(400)
return ctx.JSON(map[string]string{
"message": "password doesn't match",
})
}
password, _ := bcrypt.GenerateFromPassword([]byte(data["password"]), 14) //Mã hóa pass
user := model.User{
FirstName: data["first_name"],
LastName: data["last_name"],
Email: data["email"],
Password: string(password),
}
_, err := DB.Model(&user).Insert() //Insert database
if err != nil {
panic(err)
}
return ctx.JSON(user)
}
Bước 2:
Đăng nhập bằng cách gọi request sau và truyền dữ liệu JSON:
POSt localhost:8080/user/login
Và kết quả trả ra token đăng nhập và cookies được lưu
Code của phần này:
func Login(ctx *fiber.Ctx) error {
var data map[string]string
if err := ctx.BodyParser(&data); err != nil {
return ctx.JSON(err)
}
var user model.User
err := DB.Model(&user).Where("email = ?", data["email"]).First()
if err != nil {
ctx.Status(fiber.StatusNotFound)
return ctx.JSON(err)
}
if user.Id == 0 {
ctx.Status(fiber.StatusNotFound)
return ctx.JSON(fiber.Map{
"message": "not found",
})
}
//So sánh password nhập vào với password băm trong database
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(data["password"])); err != nil {
ctx.Status(400)
return ctx.JSON(fiber.Map{
"message": "incorrect password",
})
}
token, err := util.GenerateJWT(strconv.Itoa(user.Id)) //Tạo token đăng nhập
if err != nil {
log.Print(err)
return ctx.SendStatus(fiber.StatusInternalServerError)
}
cookie := fiber.Cookie{
Name: "jwt",
Value: token,
Expires: time.Now().Add(time.Hour * 24), //thời hạn 1 ngày
HTTPOnly: true, //Giới hạn quyền truy cập
}
ctx.Cookie(&cookie)
return ctx.JSON(token)
}
Bước 3:
Thử một request lấy thông tin user
GET localhost:8080/user
Code của phần này:
func User(ctx *fiber.Ctx) error {
cookie := ctx.Cookies("jwt") //lấy value cookie
issuer, _ := util.ParseJWT(cookie) //Parse token lấy thông tin id của user đăng nhập
var user model.User
DB.Model(&user).Where("id = ?", issuer).Relation("Posts").Select()
return ctx.JSON(user)
}
Bước 4:
Logout bằng request sau:
GET localhost:8080/logout
Thử lại request lấy thông tin user đăng nhập
Các function generate token và parse token
const SecretKey = "secret"
func GenerateJWT(issuer string) (string, error){
claims := jwt.NewWithClaims(jwt.SigningMethodHS256,jwt.StandardClaims{
Issuer: issuer,
ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),
})
return claims.SignedString([]byte(SecretKey))
}
func ParseJWT(cookie string) (string,error){
token, err := jwt.ParseWithClaims(cookie,&jwt.StandardClaims{},func(token *jwt.Token) (interface{}, error) {
return []byte("secret"),nil
})
if err != nil || !token.Valid{
return "",err
}
claims := token.Claims.(*jwt.StandardClaims)
return claims.Issuer,nil
}
Middleware
func IsAuthenticated(ctx *fiber.Ctx) error {
cookie := ctx.Cookies("jwt")
if _, err := util.ParseJWT(cookie); err != nil {
ctx.Status(fiber.StatusUnauthorized)
return ctx.JSON(fiber.Map{
"message": "unauthenticated",
})
}
return ctx.Next()
}
Chạy thử một request /api trong trạng thái chưa đăng nhập:
Kết
Vậy là trong bài này mình đã demo thử cách đăng nhập bằng JWT, lưu token vào cookies, parse token từ cookies ra và trả về thông tin đăng nhập.
Bình luận
Bài viết bổ ích
Bài viết bổ ích