5.3.5 Ngăn chặn tấn công giả mạo yêu cầu từ trang khác (CSRF)
Tấn công giả mạo yêu cầu từ trang khác (Cross-site request forgery - CSRF) là một hình thức tấn công bảo mật phổ biến. Nó liên quan đến việc lợi dụng người dùng để thực hiện một hành động trên một trang web khác thông qua mã độc được nhúng trên một trang web của kẻ tấn công. Ví dụ, người dùng có thể vô tình gửi một biểu mẫu từ trang web của kẻ tấn công đến một URL trên trang web ngân hàng của họ (trong trường hợp hệ thống đó không bảo vệ đúng cách), thực hiện hành vi như chuyển tiền mà người dùng không hề hay biết cho đến khi phát hiện tiền bị mất khỏi tài khoản.
Để chống lại các cuộc tấn công như vậy, ứng dụng có thể tạo một CSRF token khi hiển thị biểu mẫu, chèn token đó vào một trường ẩn trong biểu mẫu, và lưu trữ nó ở phía máy chủ. Khi biểu mẫu được gửi đi, token này sẽ được gửi kèm theo cùng dữ liệu biểu mẫu đến máy chủ. Máy chủ sẽ chặn yêu cầu và so sánh token nhận được với token đã tạo ban đầu. Nếu khớp nhau, yêu cầu sẽ được xử lý tiếp. Nếu không, biểu mẫu có thể đã được tạo ra từ một trang độc hại không biết token được sinh ra bởi máy chủ.
May mắn thay, Spring Security đã tích hợp sẵn tính năng bảo vệ CSRF. Hơn nữa, tính năng này được bật theo mặc định và bạn không cần phải cấu hình thêm gì cả. Bạn chỉ cần đảm bảo rằng mọi biểu mẫu gửi đi từ ứng dụng đều bao gồm một trường ẩn có tên _csrf chứa token CSRF.
Spring Security còn giúp bạn dễ dàng hơn bằng cách đặt CSRF token vào thuộc tính của request có tên _csrf. Vì vậy, bạn có thể hiển thị CSRF token trong trường ẩn bằng cách sử dụng đoạn mã Thymeleaf như sau:
<input type="hidden" name="_csrf" th:value="${_csrf.token}"/>Nếu bạn đang sử dụng thư viện thẻ JSP của Spring MVC hoặc sử dụng Thymeleaf với Spring Security dialect, bạn thậm chí không cần phải thêm thủ công trường ẩn này. Nó sẽ được tự động chèn vào biểu mẫu cho bạn.
Với Thymeleaf, bạn chỉ cần đảm bảo rằng một trong các thuộc tính của thẻ <form> là thuộc tính của Thymeleaf. Thường thì điều này không phải lo, bởi vì trong thực tế, người ta hay dùng Thymeleaf để render đường dẫn tương đối với ngữ cảnh. Ví dụ sau là đủ để Thymeleaf tự động thêm trường ẩn CSRF:
<form method="POST" th:action="@{/login}" id="loginForm">Bạn có thể tắt hỗ trợ CSRF, nhưng tôi không khuyến khích điều đó. Việc bảo vệ CSRF là rất quan trọng và hoàn toàn có thể xử lý dễ dàng trong các biểu mẫu, nên gần như không có lý do nào chính đáng để vô hiệu hóa nó. Tuy nhiên, nếu bạn vẫn muốn, bạn có thể gọi disable() như sau:
.and()
.csrf()
.disable()Một lần nữa, tôi khuyên bạn không nên tắt CSRF, đặc biệt là trong các ứng dụng sản xuất.
Toàn bộ cấu hình bảo mật ở tầng web cho ứng dụng Taco Cloud của bạn giờ đã hoàn chỉnh. Trong đó bao gồm trang đăng nhập tùy chỉnh và khả năng xác thực người dùng từ một kho dữ liệu JPA. Giờ hãy xem cách bạn có thể lấy thông tin người dùng đã đăng nhập.
