JWT là gì? Mã thông báo Web JSON được giải thích bằng một ví dụ hoạt động

  1. Trang chủ
  2. Blog
  3. Phát triển phần mềm

Phát triển phần mềm

JWT là gì? Mã thông báo Web JSON được giải thích bằng một ví dụ hoạt động

JWT cho phép máy chủ tin cậy một yêu cầu mà không cần tra cứu bất cứ điều gì. Xây dựng một cái từ đầu, cố gắng giả mạo nó và xem nó thất bại, sau đó tìm hiểu khi nào mã thông báo đánh bại các phiên và cách sử dụng chúng một cách an toàn.

Đọc 9 phút
JWT là gì? Mã thông báo Web JSON được giải thích bằng một ví dụ hoạt động

Điểm chính

  • JWT là một mã thông báo nhỏ gọn có chữ ký gồm ba phần: tiêu đề, tải trọng và chữ ký.
  • Chữ ký chứng minh mã thông báo chưa bị thay đổi nên máy chủ có thể tin cậy nó mà không cần tra cứu.
  • Tải trọng này bất kỳ ai cũng có thể đọc được, vì vậy đừng bao giờ đặt bí mật vào đó.
  • Mã thông báo khó thu hồi, vì vậy hãy giữ chúng trong thời gian ngắn và xác minh chúng bằng thư viện đáng tin cậy.

Sau khi bạn đăng nhập, làm thế nào máy chủ biết rằng mỗi yêu cầu sau đó thực sự là của bạn? Một câu trả lời phổ biến là Mã thông báo Web JSON hay JWT, thường được phát âm là “jot”. Đó là một đoạn dữ liệu nhỏ có chữ ký mà khách hàng gửi với mỗi yêu cầu và máy chủ có thể kiểm tra nó mà không cần chạm vào cơ sở dữ liệu.

Cách nhanh nhất để hiểu JWT là xây dựng một JWT và sau đó thử phá vỡ nó. Chúng tôi đã làm điều đó chỉ bằng cách sử dụng thư viện chuẩn của Python, trên Python 3.13 và kết quả đầu ra bên dưới là từ lần chạy đó. Mã này dành cho việc học. Trong ứng dụng thực tế, hãy sử dụng thư viện được bảo trì tốt vì các chi tiết xác minh rất dễ bị sai.

JWT là gì?

JWT là một tiêu chuẩn mở, được định nghĩa trong RFC 7519, để chuyển các yêu cầu giữa hai bên dưới dạng một chuỗi nhỏ gọn. Xác nhận quyền sở hữu chỉ đơn giản là một tuyên bố, chẳng hạn như “ID của người dùng này là 42”. Vì mã thông báo đã được ký nên người nhận có thể xác nhận ai đã phát hành mã thông báo đó và không ai thay đổi mã thông báo đó.

Hãy nghĩ về một chiếc vòng tay lễ hội. Nhân viên tại cổng kiểm tra vé của bạn một lần và đưa cho bạn một chiếc vòng tay khó làm giả. Sau đó, mỗi gian hàng chỉ cần nhìn ban nhạc mà không cần gọi điện tới phòng bán vé. JWT hoạt động theo cách tương tự đối với API.

Cách đăng nhập JWT hoạt động

  1. Người dùng gửi tên người dùng và mật khẩu đến điểm cuối đăng nhập.
  2. Máy chủ kiểm tra chúng và tạo mã thông báo đã ký.
  3. Khách hàng lưu trữ mã thông báo.
  4. Mỗi yêu cầu sau này đều bao gồm nó, thường ở tiêu đề: Authorization: Bearer <token>.
  5. Máy chủ xác minh chữ ký và thời hạn sử dụng, sau đó đọc các khiếu nại.

Lợi ích chính nằm ở bước 5. Máy chủ không phải tra cứu phiên, thuận tiện khi nhiều dịch vụ hoặc máy chủ cần kiểm tra cùng một token. Nếu bạn chưa quen với API, hãy bắt đầu với API là gì.

Ba phần của JWT

JWT trông giống như văn bản ngẫu nhiên, nhưng nó là ba phần được mã hóa Base64URL được phân tách bằng dấu chấm. Đây là một cái chúng tôi đã tạo:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiI0MiIsInJvbGUiOiJ1c2VyIiwiaWF0IjoxNzkzNTAwMDAwLCJleHAiOjE3OTM1MDA5MDB9
.7YfUDH_T-iDh8bMmUT8mmKYwOstzT8Ty--DTTAmQGWM

Chúng tôi đã thêm ngắt dòng để dễ đọc hơn. Giải mã hai phần đầu tiên cho JSON đơn giản:

Header:  {"alg":"HS256","typ":"JWT"}
Payload: {"sub":"42","role":"user","iat":1793500000,"exp":1793500900}
phần Chứa Mục đích
tiêu đề Loại mã thông báo và thuật toán ký Nói cách xác minh mã thông báo
Tải trọng Khiếu nại về người dùng hoặc phiên Thông tin thực tế
Chữ ký Hàm băm của hai phần đầu tiên, sử dụng khóa Chứng minh tính toàn vẹn và nguồn gốc

Yêu cầu tiêu chuẩn

Yêu cầu Tên Ý nghĩa
phụ Chủ đề Mã thông báo nói về ai, thường là ID người dùng
là Tổ chức phát hành Ai đã tạo mã thông báo
kiểm toán khán giả Mã thông báo dành cho ai
điểm kinh nghiệm Hết hạn Khi mã thông báo ngừng hợp lệ
đó Phát hành tại Khi nó được tạo ra
nbf Không phải trước đây Khi nó bắt đầu có hiệu lực
jti ID JWT ID duy nhất cho mã thông báo này

Bạn cũng có thể thêm các xác nhận quyền sở hữu tùy chỉnh, như role. Thời gian là dấu thời gian Unix, tính bằng giây. Giữ tải trọng nhỏ vì mã thông báo sẽ di chuyển theo mọi yêu cầu.

Tự mình xây dựng một cái

Việc tạo mã thông báo bao gồm việc mã hóa hai phần JSON, sau đó ký chúng bằng một bí mật bằng cách sử dụng HMAC-SHA256:

import base64, hashlib, hmac, json

SECRET = b"demo-secret-do-not-use-in-production"

def b64url(data):
    return base64.urlsafe_b64encode(data).rstrip(b"=").decode()

def sign(message):
    return b64url(hmac.new(SECRET, message.encode(), hashlib.sha256).digest())

def create_token(payload):
    header = {"alg": "HS256", "typ": "JWT"}
    parts = [
        b64url(json.dumps(header, separators=(",", ":")).encode()),
        b64url(json.dumps(payload, separators=(",", ":")).encode()),
    ]
    message = ".".join(parts)
    return message + "." + sign(message)

Quá trình xác minh hoạt động bằng cách tính toán lại chữ ký và so sánh nó với chữ ký trong mã thông báo. Chỉ người có bí mật mới có thể tạo ra bí mật phù hợp:

def verify_token(token, now):
    header, payload, signature = token.split(".")
    expected = sign(header + "." + payload)
    if not hmac.compare_digest(signature, expected):
        raise ValueError("bad signature")
    claims = json.loads(b64url_decode(payload))
    if claims["exp"] < now:
        raise ValueError("token expired")
    return claims

Mã thông báo hợp lệ đã trả lại yêu cầu của nó như mong đợi. compare_digest được sử dụng vì nó chạy trong thời gian không đổi, giúp tránh rò rỉ thông tin do chênh lệch thời gian.

Cố gắng can thiệp vào nó

Giả sử kẻ tấn công giải mã tải trọng, thay đổi "role":"user" thành "role":"admin", mã hóa lại và giữ chữ ký cũ. Chúng tôi đã thử điều này cùng với hai cuộc tấn công khác:

Cố gắng kết quả
Đã thay đổi vai trò thành quản trị viên chữ ký xấu
Đã sử dụng mã thông báo 1 giây sau khi hết hạn mã thông báo đã hết hạn
Đặt "alg":"none" và xóa chữ ký chữ ký xấu

Nỗ lực cuối cùng đó nhằm vào một điểm yếu lịch sử thực sự. Một số thư viện từng tin cậy tiêu đề riêng của mã thông báo, vì vậy kẻ tấn công có thể chỉ cần tuyên bố rằng không cần chữ ký. Mã của chúng tôi luôn sử dụng một thuật toán cố định, đó là lý do tại sao nó bị từ chối. Trong thư viện thực, hãy luôn chỉ định các thuật toán bạn chấp nhận.

Đã ký, không được mã hóa

Đây là điểm bị hiểu lầm nhiều nhất về JWT. Mã thông báo giả mạo của chúng tôi đã bị từ chối nhưng nội dung của nó vẫn hoàn toàn có thể đọc được:

{"sub":"42","role":"admin","iat":1793500000,"exp":1793500900}

Base64URL là một mã hóa, không phải mã hóa và bất kỳ ai cũng có thể đảo ngược nó mà không cần khóa. Chữ ký ngăn mọi người thay đổi dữ liệu chứ không ngăn đọc dữ liệu đó. Vì vậy, đừng bao giờ đặt mật khẩu, số thẻ hoặc dữ liệu cá nhân riêng tư vào tải trọng JWT. Nếu nội dung phải bị ẩn, hãy sử dụng mã thông báo được mã hóa (JWE) hoặc chỉ giữ dữ liệu trên máy chủ.

HS256 so với RS256

Khía cạnh HS256 RS256 hoặc ES256
Loại đối xứng Bất đối xứng
Phím Một bí mật chung Khóa riêng ký hiệu, khóa chung xác minh
Ai có thể tạo mã thông báo Bất cứ ai nắm giữ bí mật Chỉ người giữ khóa riêng
Tốt nhất cho Một dịch vụ hoặc một nhóm nhỏ đáng tin cậy Nhiều dịch vụ, bên thứ ba, nhà cung cấp danh tính

Với việc ký bất đối xứng, các dịch vụ khác có thể xác minh mã thông báo mà không thể tạo ra mã thông báo của riêng chúng, điều này sẽ hạn chế thiệt hại nếu một mã bị xâm phạm.

JWT so với phiên

JWT thường được trình bày như một sự thay thế hiện đại cho các phiên. Trong thực tế, mỗi cái đều có sự đánh đổi:

Khía cạnh Phiên máy chủ JWT
Nơi nhà nước sống Trên máy chủ Trong mã thông báo
Tra cứu theo từng yêu cầu Thông thường Không cần thiết
Đăng xuất hoặc thu hồi Dễ dàng, xóa phiên Cứng trước khi hết hạn
Kích thước theo yêu cầu ID nhỏ Mã thông báo lớn hơn (của chúng tôi là 161 ký tự)
Trên nhiều dịch vụ Cần lưu trữ chia sẻ Mỗi người có thể xác minh nó trực tiếp
Thay đổi quyền Áp dụng ngay lập tức Mã thông báo cũ vẫn có hiệu lực cho đến khi hết hạn

Đối với trang web được hiển thị trên máy chủ truyền thống, cookie phiên thường đơn giản và an toàn hơn. JWT có xu hướng có ý nghĩa hơn đối với các API được sử dụng bởi một số dịch vụ hoặc đối với ứng dụng khách trên thiết bị di động.

Mẹo: Đừng chọn JWT chỉ vì nó nghe có vẻ không trạng thái. Nhiều hệ thống thực tế thêm danh sách từ chối hoặc kiểm tra cơ sở dữ liệu để hỗ trợ đăng xuất, điều này mang lại sự tra cứu mà JWT vốn muốn tránh.

Nơi lưu trữ mã thông báo trong trình duyệt

Vị trí Rủi ro XSS Rủi ro CSRF Ghi chú
lưu trữ cục bộ Cao, vì script có thể đọc được Thấp Đơn giản nhưng có thể tiếp xúc với bất kỳ tập lệnh được chèn nào
HttpOnly cookie Thấp hơn, vì script không thể đọc được Cần bảo vệ Sử dụng Secure và SameSite
Biến trong bộ nhớ Hạ xuống Thấp Mất khi làm mới, vì vậy nó cần một luồng làm mới

Nhiều hướng dẫn bảo mật ưu tiên cookie HttpOnly, Secure, SameSite cho ứng dụng web. Dù bạn chọn cách nào, hãy luôn sử dụng HTTPS. Để gửi mã thông báo từ JavaScript, hãy xem Hướng dẫn API tìm nạp JavaScript của chúng tôi.

Làm mới mã thông báo

Thời hạn sử dụng ngắn sẽ hạn chế thiệt hại do mã thông báo bị đánh cắp, nhưng không ai muốn đăng nhập sau mỗi 15 phút. Giải pháp thông thường sử dụng hai mã thông báo:

  • Mã thông báo truy cập: tồn tại trong thời gian ngắn, chẳng hạn như số phút và được gửi cùng với mọi yêu cầu API.
  • Mã thông báo làm mới: tồn tại lâu hơn, được lưu trữ cẩn thận hơn và chỉ được sử dụng để nhận mã thông báo truy cập mới.

Máy chủ theo dõi các mã thông báo làm mới, do đó, nó có thể thu hồi chúng, giúp bạn đăng xuất một cách thiết thực. Xoay chúng trong mỗi lần sử dụng cũng giúp bạn phát hiện hành vi trộm cắp vì mã thông báo cũ bị đánh cắp sẽ được phát lại.

Những lỗi bảo mật thường gặp

  • Giải mã mà không cần xác minh. Việc đọc tải trọng không làm cho nó trở nên đáng tin cậy. Luôn kiểm tra chữ ký.
  • Chấp nhận bất kỳ thuật toán nào. Đặt danh sách rõ ràng các thuật toán được phép.
  • Sử dụng bí mật yếu. Bí mật ngắn có thể bị bẻ khóa ngoại tuyến. Sử dụng một giá trị ngẫu nhiên dài và giữ nó ngoài tầm kiểm soát nguồn.
  • Bỏ qua thời hạn sử dụng. Token không có exp có thể hoạt động mãi mãi nếu bị đánh cắp.
  • Không kiểm tra iss và aud. Nếu không, mã thông báo được cấp cho một dịch vụ có thể được dịch vụ khác chấp nhận.
  • Tin vào các tuyên bố cũ. Vai trò bên trong mã thông báo có thể lỗi thời cho đến khi hết hạn.
  • Mã thông báo ghi nhật ký. Bất kỳ ai đọc nhật ký của bạn đều có thể sử dụng lại chúng.
  • Không kiểm tra các đường dẫn lỗi. Thêm các thử nghiệm cho các mã thông báo đã hết hạn và đã sửa đổi cũng như các mã thông báo hợp lệ. Hướng dẫn kiểm tra API bằng Postman của chúng tôi có thể giúp ích.

Lời kết

JWT là dữ liệu đã được ký mà máy chủ có thể tin cậy mà không cần tra cứu, không phải là vùng chứa bí mật và không phải là bản nâng cấp tự động qua các phiên. Sử dụng thời hạn sử dụng ngắn, xác minh mọi thứ bằng thư viện được duy trì và loại bỏ dữ liệu riêng tư khỏi tải trọng. Để tự mình xem, hãy chạy một tập lệnh nhỏ như của chúng tôi, thay đổi một ký tự của mã thông báo và xem quá trình xác minh không thành công.

Câu hỏi thường gặp

JWT dùng để làm gì?

JWT chủ yếu được sử dụng để xác thực và ủy quyền trong API. Sau khi đăng nhập, khách hàng sẽ gửi mã thông báo với mỗi yêu cầu và máy chủ sẽ xác minh nó để xác định người dùng.

JWT có được mã hóa không?

Thường thì không. JWT tiêu chuẩn được ký và mã hóa để bất kỳ ai cũng có thể đọc được tải trọng của nó. Chữ ký chỉ ngăn chặn những thay đổi. Mã thông báo được mã hóa sử dụng định dạng liên quan được gọi là JWE.

JWT nên tồn tại trong bao lâu?

Mã thông báo truy cập thường tồn tại trong thời gian ngắn, thường là vài phút thay vì vài ngày. Ghép nối chúng với mã thông báo làm mới để người dùng không phải đăng nhập liên tục.

JWT có thể bị thu hồi không?

Không phải tự nó, vì nó vẫn có hiệu lực cho đến khi hết hạn. Việc thu hồi yêu cầu theo dõi phía máy chủ, chẳng hạn như danh sách từ chối, loại bỏ một số lợi ích không có trạng thái.

JWT có tốt hơn phiên không?

Không phải lúc nào cũng tốt hơn. Phiên thu hồi đơn giản hơn và phù hợp với nhiều trang web, trong khi JWT phù hợp với các API và dịch vụ cần xác minh danh tính một cách độc lập.

Tiếp tục học hỏi

Làm việc với Stack Quora

Cần trợ giúp về kiểm tra, WordPress hoặc SEO?

Chúng tôi giúp các nhóm phát triển phần mềm tốt hơn và phát triển trang web của họ. Hãy cho chúng tôi biết bạn đang làm gì và chúng tôi sẽ đề xuất bước tiếp theo rõ ràng.

Tiếp tục đọc

Thêm hướng dẫn về thử nghiệm, AI và phát triển hiện đại

Bạn thích bài viết này? Chọn một chủ đề và chuyển ngay sang phần hướng dẫn mới nhất của chúng tôi.

Trí tuệ nhân tạo

Giải thích về ảo giác AI: Tại sao các mô hình ngôn ngữ lại tạo nên mọi thứ và cách giảm thiểu nó

Ảo giác AI đã giải thích: chúng là gì, tại sao mô hình ngôn ngữ tạo ra chúng, các loại phổ biến, cách giảm thiểu chúng bằng cách căn cứ và nhắc nhở …

Đọc bài viết →
DevOps

Giải thích về các biến môi trường: Tệp .env, bí mật và cấu hình được thực hiện đúng

Các biến môi trường được giải thích bằng các ví dụ Python mà chúng tôi đã chạy: đọc và thiết lập chúng, tại sao mọi giá trị đều là một chuỗi, tệp .e…

Đọc bài viết →
Phát triển phần mềm

Giải thích về giới hạn tỷ lệ API: Thuật toán, tiêu đề và xử lý lỗi 429

Giới hạn tốc độ API được giải thích bằng mô phỏng mà chúng tôi đã chạy: nhóm mã thông báo, cửa sổ cố định, cửa sổ trượt, 429 phản hồi, tiêu đề giới …

Đọc bài viết →
Tự động hóa kiểm thử

Chế giễu bằng Python: unittest.mock, patch và những sai lầm khiến bài kiểm tra nói dối

Mô phỏng bằng Python với unittest.mock, đã được thử nghiệm: Mock và return_value, side_effect, vá lỗi nơi sử dụng tên, thông số kỹ thuật và thông số…

Đọc bài viết →
Kiểm thử phần mềm

Giải thích về phạm vi bảo hiểm của mã: Phạm vi tuyến so với chi nhánh và ý nghĩa thực sự 100%

Phạm vi bảo hiểm mã được giải thích bằng cách chạy phạm vi bảo hiểm thực tế: phạm vi bảo hiểm dòng, chi nhánh và điều kiện, đọc báo cáo, lý do tại s…

Đọc bài viết →
Cơ sở dữ liệu & SQL

DELETE vs TRUNCATE vs DROP trong SQL: Sự khác biệt, khôi phục và thời điểm sử dụng mỗi loại

DELETE vs TRUNCATE vs DROP được giải thích bằng SQL đã được thử nghiệm: mỗi loại loại bỏ, khôi phục, kích hoạt, đặt lại danh tính, tốc độ và Postgre…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích về Chế độ xem SQL: Tạo, sử dụng và tránh những cạm bẫy, kèm theo ví dụ

Chế độ xem SQL được giải thích bằng các truy vấn chúng tôi đã chạy: tạo chế độ xem, kết quả trực tiếp, ẩn cột, hiệu suất, chế độ xem có thể cập nhật…

Đọc bài viết →
Phát triển phần mềm

Giao diện TypeScript so với loại: Sự khác biệt thực sự, được thử nghiệm bằng trình biên dịch

Giao diện TypeScript so với loại, được kiểm tra bằng trình biên dịch thực: cả hai có thể làm gì, chỉ một người có thể làm gì, hợp nhất khai báo, mở …

Đọc bài viết →
Phát triển phần mềm

Giải thích về Python *args và **kwargs: Hàm linh hoạt với ví dụ rõ ràng

Python *args và **kwargs được giải thích bằng mã chúng tôi đã chạy: đóng gói và giải nén, thứ tự tham số, đối số chỉ từ khóa và chỉ vị trí, trình tr…

Đọc bài viết →
Phát triển phần mềm

Hàm Lambda của Python: Cú pháp, cách sử dụng thực tế và khi nào không nên sử dụng chúng

Các hàm lambda của Python được giải thích bằng mã chúng tôi đã chạy: cú pháp, sắp xếp bằng khóa, bản đồ và bộ lọc, các phần đóng, bẫy liên kết muộn …

Đọc bài viết →
Trí tuệ nhân tạo

Đại lý AI là gì? Cách chúng hoạt động, với vòng lặp tác nhân đơn giản, bạn có thể chạy

Tác nhân AI là gì? Hướng dẫn đơn giản về vòng lặp tác nhân, công cụ, bộ nhớ và lan can, với một vòng lặp Python nhỏ mà chúng tôi đã chạy, những rủi …

Đọc bài viết →
DevOps

Giám sát và Khả năng quan sát: Sự khác biệt thực sự, với nhật ký, số liệu và dấu vết

Giải thích về giám sát và khả năng quan sát: lỗi đã biết và chưa biết, nhật ký, số liệu và dấu vết, hướng dẫn về sự cố thanh toán, tín hiệu vàng, Op…

Đọc bài viết →
DevOps

Docker Volumes vs Bind Mounts: Duy trì dữ liệu vùng chứa đúng cách

Giải thích về khối lượng Docker và liên kết gắn kết: tại sao dữ liệu vùng chứa biến mất, khối lượng được đặt tên, liên kết gắn kết, tmpfs, ví dụ về …

Đọc bài viết →
Tự động hóa kiểm thử

TDD vs BDD: Key Differences, One Feature Built Both Ways and When to Use Each

TDD và BDD được giải thích bằng một tính năng giảm giá được xây dựng theo cả hai cách: tái cấu trúc màu đỏ-xanh với mã chúng tôi đã chạy, kịch bản C…

Đọc bài viết →
Kiểm thử phần mềm

Kiểm tra chấp nhận của người dùng (UAT): Quy trình, danh sách kiểm tra và ví dụ thực tế

Giải thích về thử nghiệm chấp nhận của người dùng: ai chạy nó, nó khác với QA như thế nào, quy trình bảy bước, mẫu trường hợp thử nghiệm UAT, danh s…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích về các giá trị NULL của SQL: IS NULL, COALESCE, NULLIF và những cái bẫy cần tránh

Các giá trị SQL NULL được giải thích bằng các truy vấn chúng tôi đã chạy: logic ba giá trị, IS NULL, COALESCE, NULLIF, cách tổng hợp, kết hợp và sắp…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Câu lệnh SQL CASE WHEN: Cú pháp, ví dụ thực tế và các lỗi thường gặp

TRƯỜNG HỢP SQL KHI được giải thích bằng các truy vấn mà chúng tôi đã chạy: các biểu mẫu đơn giản và được tìm kiếm, thứ tự điều kiện, các thủ thuật S…

Đọc bài viết →
Phát triển phần mềm

JWT là gì? Mã thông báo Web JSON được giải thích bằng một ví dụ hoạt động

JWT là gì? Mã thông báo Web JSON đã giải thích: ba phần, mã thông báo được xây dựng và giả mạo trong mã chúng tôi đã chạy, JWT so với phiên, lưu trữ…

Đọc bài viết →
Phát triển phần mềm

Giải thích về vòng lặp sự kiện JavaScript: Ngăn xếp cuộc gọi, Microtask và bộ hẹn giờ kèm ví dụ

Vòng lặp sự kiện JavaScript được giải thích bằng mã chúng tôi đã chạy: ngăn xếp cuộc gọi, hàng đợi tác vụ và vi nhiệm, tại sao setTimeout 0 không di…

Đọc bài viết →
Phát triển phần mềm

Giải thích về trình tạo và năng suất của Python: Tiết kiệm bộ nhớ bằng các ví dụ thực tế

Trình tạo và lợi nhuận Python được giải thích bằng mã chúng tôi đã chạy: cách chúng tạm dừng và tiếp tục, đo mức tiết kiệm bộ nhớ, quy trình, chuỗi …

Đọc bài viết →
Trí tuệ nhân tạo

Nhúng là gì? Giải thích sự tương đồng về vectơ và Cosine một cách đơn giản

nhúng là gì? Hướng dẫn bằng ngôn ngữ đơn giản về vectơ, độ tương tự cosine và tìm kiếm ngữ nghĩa, với một ví dụ nhỏ mà chúng tôi đã chạy, các cách s…

Đọc bài viết →
DevOps

Triển khai Blue-Green và Canary: Sự khác biệt, sự đánh đổi và cách lựa chọn

Giải thích về triển khai Blue-green và Canary: cách hoạt động của từng loại, chi phí, rủi ro và khôi phục, nhóm người dùng ổn định mà chúng tôi đã t…

Đọc bài viết →
Phát triển phần mềm

Git merge vs rebase: khác biệt, ví dụ và khi nào dùng cái nào

Git merge vs rebase được giải thích bằng đầu ra log thực tế, bảng so sánh, quy tắc vàng của rebase và quy trình làm việc nhóm an toàn.

Đọc bài viết →
Phát triển phần mềm

List comprehension trong Python: cú pháp, ví dụ và khi nào nên tránh

List comprehension trong Python: cú pháp, lọc dữ liệu, if-else, vòng lặp lồng nhau, thời gian đo thực tế và khi nào vòng lặp for thông thường tốt hơn.

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích SQL JOIN kèm ví dụ (Inner, Left, Right, Full)

Hiểu SQL JOIN từng bước với bảng và truy vấn mẫu: INNER, LEFT, RIGHT, FULL, CROSS và SELF, cùng lỗi thường gặp và mẹo hiệu năng.

Đọc bài viết →