☰ Mục lục series
Tài liệu Go tiếng Việt
  1. Bắt đầu (Getting started)
    1. Tổng quan
    2. Tải về và cài đặt
    3. Bắt đầu với Go
    4. Quản lý các bản cài đặt Go
    5. Plugin trình soạn thảo và IDE
  2. Dạo quanh Go (A Tour of Go)
    1. Chào mừng
    2. Package, biến và hàm
    3. Điều khiển luồng
    4. Struct, slice và map
    5. Method và interface
    6. Generics
    7. Xử lý đồng thời
  3. Hướng dẫn (Tutorials)
    1. Danh sách hướng dẫn
    2. Tạo một Go module
    3. Gọi mã của bạn từ một module khác
    4. Trả về và xử lý lỗi
    5. Trả về lời chào ngẫu nhiên
    6. Trả về lời chào cho nhiều người
    7. Thêm một test
    8. Biên dịch và cài đặt ứng dụng
    9. Kết luận
    10. Bắt đầu với workspace nhiều module
    11. Phát triển RESTful API với Go và Gin
    12. Truy cập cơ sở dữ liệu quan hệ
    13. Bắt đầu với generics
    14. Bắt đầu với fuzzing
    15. Làm việc với JSON
    16. Tìm và sửa các dependency có lỗ hổng với govulncheck
    17. Tìm và khắc phục phụ thuộc có lỗ hổng với VS Code Go
    18. Viết ứng dụng web
  4. Viết code Go
    1. Cách viết mã Go
    2. Effective Go
    3. Doc Comment trong Go
  5. Module
    1. Phát triển và publish module
    2. Quản lý phụ thuộc
    3. Tổ chức một module Go
    4. Quản lý mã nguồn của module
    5. Cách đánh số phiên bản module
    6. Quy trình phát hành và đánh phiên bản module
    7. Publish một module
    8. Phát triển một bản cập nhật major version
    9. Tham chiếu tệp go.mod
    10. Ngừng hỗ trợ 'go get' cho việc cài đặt tệp thực thi
  6. Cơ sở dữ liệu (Database)
    1. Truy cập cơ sở dữ liệu quan hệ
    2. Mở một handle cơ sở dữ liệu
    3. Thực thi câu lệnh SQL không trả về dữ liệu
    4. Truy vấn dữ liệu
    5. Dùng prepared statement
    6. Thực thi transaction
    7. Huỷ các thao tác đang chạy
    8. Quản lý kết nối
    9. Tránh rủi ro SQL injection
  7. Chẩn đoán và hiệu năng
    1. Chẩn đoán
    2. Hướng dẫn về Go Garbage Collector
    3. Tối ưu hoá dựa trên profile
    4. Data Race Detector
    5. Gỡ lỗi mã Go bằng GDB
    6. Hỗ trợ coverage profiling cho integration test
  8. Bảo mật (Security)
    1. Tổng quan bảo mật
    2. Thực hành tốt về bảo mật cho lập trình viên Go
    3. Quản lý lỗ hổng trong Go
    4. Cơ sở dữ liệu lỗ hổng của Go
    5. Quét lỗ hổng trong IDE
    6. Chính sách CNA của Go
    7. Go Fuzzing
    8. Chi tiết kỹ thuật của Go Fuzzing
    9. Chính sách bảo mật của Go
    10. Threat Model của Go
    11. Các quyết định về bảo mật của Go
    12. Tuân thủ FIPS 140-3
  9. Công cụ và toolchain
    1. Tài liệu về các lệnh
    2. Về lệnh go
    3. Go Toolchains
    4. Telemetry của Go
    5. Cài đặt Go từ mã nguồn
    6. Cài đặt và sử dụng gccgo
  10. Tham khảo
    1. Câu hỏi thường gặp (FAQ)
    2. Go 1 và tương lai của các chương trình Go
    3. Hướng dẫn chuyển đổi sang encoding/json/v2
    4. Hướng dẫn đóng góp
    5. Đóng góp cho frontend gccgo
  11. Phụ lục
    1. Bảng thuật ngữ
Cơ sở dữ liệu (Database)

Tránh rủi ro SQL injection

Bản dịch từ go.dev/doc/database/sql-injection

Bạn có thể tránh rủi ro SQL injection bằng cách truyền giá trị tham số SQL vào dưới dạng đối số của hàm trong package sql. Nhiều hàm trong package sql cung cấp tham số cho câu lệnh SQL và tham số cho các giá trị sẽ được dùng trong những tham số của câu lệnh đó (một số hàm khác thì cung cấp tham số cho prepared statement và các tham số của nó).

Mã trong ví dụ sau dùng ký hiệu ? làm placeholder cho tham số id, giá trị của nó được truyền vào dưới dạng đối số của hàm:

// Correct format for executing an SQL statement with parameters.
rows, err := db.Query("SELECT * FROM user WHERE id = ?", id)

Các hàm của package sql thực hiện thao tác cơ sở dữ liệu sẽ tạo ra prepared statement từ những đối số bạn cung cấp. Khi chạy, package sql biến câu lệnh SQL thành một prepared statement rồi gửi nó đi kèm với tham số, và tham số được tách riêng.

Lưu ý: Placeholder cho tham số thay đổi tuỳ theo DBMS và driver bạn đang dùng. Ví dụ, driver pq dành cho Postgres chấp nhận dạng placeholder như $1 thay cho ?.

Bạn có thể bị cám dỗ dùng một hàm của package fmt để ghép câu lệnh SQL thành chuỗi có sẵn tham số bên trong – như thế này:

// SECURITY RISK!
rows, err := db.Query(fmt.Sprintf("SELECT * FROM user WHERE id = %s", id))

Cách này không an toàn! Khi bạn làm vậy, Go ghép toàn bộ câu lệnh SQL, thay động từ định dạng %s bằng giá trị tham số, trước khi gửi trọn câu lệnh tới DBMS. Điều này tạo ra rủi ro SQL injection, vì phía gọi mã của bạn có thể gửi một đoạn SQL ngoài dự kiến vào làm đối số id. Đoạn đó có thể hoàn thiện câu lệnh SQL theo những cách không lường trước được và nguy hiểm cho ứng dụng của bạn.

Ví dụ, bằng cách truyền vào một giá trị %s nhất định, bạn có thể nhận được thứ gì đó như sau, và nó có thể trả về toàn bộ bản ghi người dùng trong cơ sở dữ liệu của bạn:

SELECT * FROM user WHERE id = 1 OR 1=1;

Nội dung gốc: Go Documentation © The Go Authors, giấy phép CC BY 3.0. Bản dịch và ghi chú: Lê Văn Dũng.