首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Spring Security 4 + Tomcat 7 啟動卡住無報錯?罪魁禍首是 BCryptPasswordEncoder 初始化極慢

     編輯:程式設計綜合問答

現象

  • 整合 Spring Security 4 後,Tomcat 7 啟動到「初始化 bean」階段卡住,無異常、無報錯、CPU 低佔用。
  • 移除 Security 配置即正常啟動。

排查過程

  1. 檢查 `web.xml`、`applicationContext-security.xml` 配置無誤。
  2. 斷點調試發現卡在 `AuthenticationManagerBuilder` 構建 `DaoAuthenticationProvider` 時。
  3. 進一步定位到 `BCryptPasswordEncoder` 的構造函數內部調用 `SecureRandom` 生成強隨機種子。
  4. Linux 環境下 `/dev/random` 熵池不足導致 `SecureRandom` 陰塞,等待熵積累,耗時數分鐘甚至更久。

根因

`BCryptPasswordEncoder` 預設使用 `SecureRandom`(基於 `/dev/random`)生成鹽值,Linux 熵池不足導致阻塞。

解決方案(任選其一)

方案一:配置使用 `/dev/urandom`(非阻塞,安全性略降但通常可接受)

<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <constructor-arg index="0" value="10" /> <!-- strength -->
    <constructor-arg index="1">
        <bean class="java.security.SecureRandom" factory-method="getInstance">
            <constructor-arg value="SHA1PRNG" />
            <constructor-arg value="SUN" />
        </bean>
    </constructor-arg>
</bean>

# 或者在 JVM 啟動參數添加(推薦,全局生效)
-Djava.security.egd=file:/dev/./urandom

方案二:改用 `StandardPasswordEncoder`(SHA-256,速度快,無阻塞)

<bean id="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" />

方案三:預熱熵池(治本,需運維配合)

  • 安裝 `haveged` 或 `rng-tools` 守護進程,持續向熵池注入隨機數。
  • 虛擬機環境確保啟用 `virtio-rng` 設備傳遞宿主機熵。

驗證

添加 `-Djava.security.egd=file:/dev/./urandom` 後,Tomcat 啟動從「卡住 3 分鐘」縮減至「10 秒內完成」。

避坑指南

  • **生產環境 Linux 必加** `-Djava.security.egd=file:/dev/./urandom`,避免啟動超時被監控系統誤判為失敗。
  • Spring Boot 2.x 已內部優化,但手動配置 `BCryptPasswordEncoder` 時仍需注意。
  • 單元測試環境同理,加快測試啟動速度。

記住:**Security 啟動慢 90% 是 BCrypt + /dev/random 熵不足**,一行 JVM 參數即可治愈。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved