#java
Вопрос:
У меня возникла проблема со следующим кодом
public static void main(String[] args) throws NoSuchAlgorithmException { String key = "test"; SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA512"); Mac mac = Mac.getInstance("HmacSHA512"); try { if (null != mac) { mac.init(secretKeySpec); } } catch (InvalidKeyException e) { } IntStream.range(1, 12).parallel().forEach(d-gt;{ final byte[] bytes = "somestring".getBytes(StandardCharsets.UTF_8); final byte[] doFinal= mac.doFinal(bytes); String digest = Base64.getEncoder().encodeToString(doFinal); LOGGER.info("digest -- {} ", digest); }); }
Даже строка та же самая, но дайджесты, созданные с помощью mac.doFinal, отличаются. Это всего лишь демонстрация проблемы. Я использовал тот же код в своем приложении spring reactive, где mac-это компонент, и дайджест генерируется каждый раз, когда пользователь делает запрос, который является параллельным запросом, где я также видел это странное поведение.
Комментарии:
1. Вы вызываете
mac.doFinal
параллельно в одном экземпляре. По-моему, это плохая идея. Вы получаете противоречивые результаты, если просто используете обычныйfor
цикл и создаете MAC последовательно?2. (Если вам нужно выполнять операции параллельно, создайте новый
Mac
экземпляр в цикле.)3. Цикл последовательности прекрасен, но есть реальный сценарий, например, у меня есть компонент mac, и я сгенерировал дайджест заголовков с помощью mac.doFinal (). это параллельный запрос в приложении шлюза. Теперь есть базовое приложение, которое снова генерирует дайджест для одних и тех же данных и сравнивает оба дайджеста, так что на этот раз это создаст проблему.
4. Параллельные запросы должны быть в порядке: до тех пор, пока каждый из них использует новый
Mac
экземпляр. Итак, как я уже сказал, для вашего тестового кода переместитеMac
создание в телоforEach
лямбды. По сути, проблема заключается в том, что вы одновременно изменяете общее состояние — вы не можете этого сделать и ожидать, что результаты будут действительными.5. Создание экземпляра Mac каждый раз в приложении шлюза-дорогостоящая задача. Я переместил экземпляр Mac внутрь, теперь он работает нормально, но я не уверен в реальной причине, по которой mac.doFinal не генерирует один и тот же дайджест для одних и тех же данных?