JWT ví dụ mẫu

29 tháng 07, 2021 - 2132 lượt xem

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).

Source code

Đ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

12

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

1

5

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

6

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

s

Thử lại request lấy thông tin user đăng nhập

d

Các function generate token và parse token

Bấm vào đây để xem đầy đủ

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

Bấm vào đây để xem đầy đủ

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:

a

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

avatar
Trịnh Minh Cường 2021-07-30 03:03:52.109367 +0000 UTC
  1. Bài viết này thiếu phần kết luận. Đọc một đoạn dài chả biết tác giả làm được gì
  2. Thông thường người ta không lưu JWT token vào Cookie bởi JWT được thiết kế để khắc phục nhược điểm của Cookie là cookie chỉ được xem giới hạn trong domain nó được tạo ra, Cookie không được hỗ trợ trong ứng dụng native mobile app.
  3. Thực tế JWT được lưu trong key Authorization phần header của Request gửi lên
Avatar
avatar
Bùi Hiên 2021-08-01 14:34:23.895506 +0000 UTC

Bài viết bổ ích

Avatar
avatar
Trịnh Viết Linh 2021-09-07 11:56:43.185503 +0000 UTC

Bài viết bổ ích

Avatar
* Vui lòng trước khi bình luận.
Ảnh đại diện
  +1 Thích
+1