JuniorTypeScript

Vì sao phải kiểm tra dữ liệu đầu vào ở phía server dù TypeScript đã có kiểu?

Người phỏng vấn muốn biết bạn có phân biệt được kiểu lúc biên dịch với dữ liệu thật lúc chạy, và có nghĩ tới việc dữ liệu từ bên ngoài không đáng tin hay không.

Kiểu TypeScript chỉ tồn tại khi bạn viết và biên dịch code. Khi chương trình chạy, kiểu đã bị xóa, nên JSON.parse(body) trả về bất cứ thứ gì người gửi đưa vào, và việc viết as Order chỉ là bạn tự hứa với trình biên dịch, không kiểm tra gì cả. Dữ liệu từ request, từ file, từ API khác đều là dữ liệu không tin cậy cho tới khi được kiểm tra.

Hậu quả của việc không kiểm tra:

  1. Lỗi lặng lẽ. Số lượng là chữ làm phép nhân ra NaN, rồi thành null khi chuyển sang JSON, và tổng tiền sai mà không có lỗi nào.
  2. Lỗi lan rộng. Một bản ghi thiếu trường làm hàm xử lý ném lỗi, và nếu hàm đó chạy trên cả danh sách thì một dữ liệu hỏng làm hỏng mọi người.
  3. Lỗ hổng bảo mật. Người gửi có thể đặt cả những trường họ không được phép đặt, như id hay quyền hạn.

Cách làm đúng là kiểm tra ngay ở nơi dữ liệu đi vào hệ thống, bằng một thư viện schema như Zod: khai báo hình dạng hợp lệ, gọi safeParse, trả lỗi 400 kèm danh sách lỗi theo từng trường nếu sai. Sau bước đó, phần còn lại của code dùng kiểu do schema suy ra và tin vào nó. Nên khai báo dữ liệu nhận về là unknown thay vì any, để trình biên dịch buộc bạn kiểm tra trước khi dùng.

Ý quan trọng để nêu: kiểm tra một lần ở cửa, không rải khắp nơi, và phân biệt lỗi do người gửi (400) với lỗi của máy chủ (500).

Điểm cộng: nhắc tới việc giới hạn kích thước nội dung gửi lên, và chọn có cho phép trường lạ hay không (từ chối hẳn thường an toàn hơn lặng lẽ bỏ qua).