Статьи

Исправление распространенных нарушений кода безопасности Java в сонаре


Цель этой статьи — показать, как быстро исправить наиболее распространенные нарушения кода безопасности Java. Предполагается, что вы знакомы с концепцией правил и нарушений кода и с тем, как
Sonar сообщает о них. Однако, если вы не слышали этих терминов раньше, вы можете взглянуть на
Sonar Concepts  или на
будущую книгу о Sonar  для более подробного объяснения.

Чтобы понять, во время анализа Sonar ваш проект сканируется многими инструментами, чтобы убедиться, что исходный код соответствует правилам, которые вы создали в своем профиле качества . Всякий раз, когда правило нарушается … ну, нарушение возникает. С помощью Sonar вы можете отслеживать эти нарушения, просматривая информацию о нарушениях или в редакторе исходного кода. Существуют сотни правил, классифицированных в зависимости от их важности. В следующих статьях я постараюсь охватить как можно больше, но сейчас давайте рассмотрим некоторые общие правила / нарушения безопасности. Есть две пары правил (все они оцениваются как критические в сонаре), которые мы собираемся рассмотреть прямо сейчас.

1. Массив хранится напрямую ( PMD ), а метод возвращает внутренний массив (  PMD  )

Эти нарушения появляются в тех случаях, когда внутренний массив сохраняется или возвращается непосредственно из метода. В следующем примере показан простой класс, который нарушает эти правила.

public class CalendarYear {
 private String[] months;
 public String[] getMonths() {
    return months;    
 }
 public void setMonths(String[] months) {
    this.months = months;
 }
}

Чтобы устранить их, вы должны клонировать массив перед его сохранением / возвратом, как показано в следующей реализации класса, чтобы никто не мог изменить или получить исходные данные вашего класса, а только их копию.

public class CalendarYear {
 private String[] months;
 public String[] getMonths() {
    return months.clone();    
 }
 public void setMonths(String[] months) {
    this.months = months.clone();
 }
}

2. Непостоянная строка, переданная методу выполнения в операторе SQL ( findbugs ), и подготовленный оператор генерируется из непостоянной строки (findbugs )

Оба правила связаны с доступом к базе данных при использовании библиотек JDBC. Как правило, существует два способа выполнения командлетов SQL через соединение JDBC: Statement и PreparedStatement. Существует много дискуссий о плюсах и минусах, но это выходит за рамки этого поста. Давайте посмотрим, как возникает первое нарушение, основываясь на следующем фрагменте исходного кода.

Statement stmt = conn.createStatement();
String sqlCommand = "Select * FROM customers WHERE name = '" + custName + "'";
stmt.execute(sqlCommand);

Вы уже заметили, что  параметр sqlcommand, передаваемый методу execute, динамически создается во время выполнения, что неприемлемо для этого правила. Подобные ситуации вызывают второе нарушение.

String sqlCommand = "insert into customers (id, name)  values (?, ?)";
Statement stmt = conn.prepareStatement(sqlCommand);

Вы можете преодолеть эту проблему тремя различными способами. Вы можете использовать  StringBuilder или string.Format  метод для создания значений строковых переменных. Если применимо, вы можете определить команды SQL как константы в объявлении класса, но это только для случая, когда команду SQL не требуется изменять во время выполнения. Давайте перепишем первый фрагмент кода, используя StringBuilder

Statement stmt = conn.createStatement();
stmt.execute(new StringBuilder("Select FROM customers WHERE name = '").
                         append(custName).
                         append("'").toString());

и используя String.format

Statement stmt = conn.createStatement();
String sqlCommand = String.format("Select * from customers where name = '%s'", custName);
stmt.execute(sqlCommand);

Для второго примера вы можете просто объявить sqlCommand следующим образом

private static final SQLCOMMAND = insert into customers (id, name)  values (?, ?)";

Существуют и другие правила безопасности, такие как блокирующий постоянный пароль базы данных, жестко закодированный, но я предполагаю, что никто не все еще жестко кодирует пароли в файлах исходного кода…

В следующих статьях я собираюсь показать вам, как придерживаться правил производительности и плохой практики. До тех пор я жду ваших комментариев или предложений.