Có thể sử dụng nối để tạo ra chuỗi của bạn. Làm như vậy không gây ra cảnh báo Bảo mật.Và thích hợp hơn vì lợi ích của sự rõ ràng khi xử lý các câu lệnh SQL dài sẽ được chia nhỏ hơn trên nhiều dòng
Sử dụng các biến để tạo chuỗi là nguyên nhân gây ra cảnh báo bảo mật.
Điều này sẽ gây ra cảnh báo:
String columnName = getName();
String tableName = getTableName();
final String sql = "SELECT MAX(" + columnName + ") FROM " + tableName;
PreparedStatement ps = connection.prepareStatement(sql);
này sẽ không không làm việc:
String columnName = getName();
String tableName = getTableName();
final String sql = "SELECT MAX(" + "?" + ")" +
"FROM " + "?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, columnName);
ps.setString(2, tableName);
Nó không làm việc vì chuẩn bị phát biểu chỉ cho phép các thông số bị ràng buộc cho "giá trị" bit của Câu lệnh sql.
Đây là giải pháp mà làm việc:
private static final boolean USE_TEST_TABLE = true;
private static final boolean USE_RESTRICTED_COL = true;
private static final String TEST_TABLE = "CLIENT_TEST";
private static final String PROD_TABLE = "CLIENT";
private static final String RESTRICTED_COL ="AGE_COLLATED";
private static final String UNRESTRICTED_COL ="AGE";
....................
final String sql = "SELECT MAX(" +
(USE_RESTRICTED_COL ? RESTRICTED_COL : UNRESTRICTED_COL) + ")" +
"FROM " +
(USE_TEST_TABLE ? TEST_TABLE : PROD_TABLE);
PreparedStatement ps = connectComun.prepareStatement(sql);
Nhưng nó chỉ hoạt động nếu bạn phải lựa chọn giữa hai bảng có tên được biết tại thời gian biên dịch. Bạn có thể sử dụng các toán tử bậc ba phức tạp cho hơn 2 trường hợp nhưng sau đó nó trở thành không thể đọc được.
Trường hợp đầu tiên có thể là vấn đề bảo mật nếu getName() hoặc getTableName() lấy tên từ các nguồn không đáng tin cậy.
Có thể xây dựng một câu lệnh SQL an toàn sử dụng các biến nếu các biến đó đã được xác minh trước đó. Đây là trường hợp của bạn, nhưng FindBugs không thể tìm ra. Findbugs không thể biết được những nguồn nào đáng tin cậy hay không.
Nhưng nếu bạn phải sử dụng tên cột hoặc bảng từ người dùng hoặc đầu vào không tin cậy thì không có cách nào xung quanh nó. Bạn phải xác minh chính mình chuỗi đó và bỏ qua cảnh báo Findbugs với bất kỳ phương pháp nào được đề xuất trong các câu trả lời khác.
Kết luận: Không có giải pháp hoàn hảo cho trường hợp chung của câu hỏi này.
Xin chào người dùng714965, cảm ơn bạn đã trả lời. Tôi có những lần xuất hiện khác của cảnh báo này bằng cách sử dụng StringBuilder, do đó nó không hoạt động. Chú thích hoạt động (rất tốt để làm rõ cho người đọc khác rằng tên đầy đủ của nó là @ edu.umd.cs.findbugs.annotations.SuppressWarnings). Bây giờ tôi phải quyết định nếu tôi muốn lib FindBugs trong dự án của tôi hay không. Cảm ơn một lần nữa. – ederribeiro
@ederribeiro: Sự phụ thuộc vào FindBugs từ dự án của bạn có thể không phải là điều tốt nhất bạn nói đúng. Trong câu trả lời ban đầu của tôi, tôi đã bỏ lỡ một điểm, xin vui lòng xem đoạn cuối. – Kai
Điều này giải quyết vấn đề cụ thể này bởi vì OP chắc chắn rằng mã của mình được an toàn khỏi SQL INJECTION. Nhưng đó là lỗi dễ bị và do đó một thực hành xấu nói chung. Các câu lệnh được chuẩn bị với các tham số là cách để đi. Sẽ không bỏ phiếu tiêu cực vì nó thực sự giải quyết các câu hỏi nhưng tôi khuyên không nên làm theo cách đó. –