首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

J2EE 工程實戰:常見安全漏洞與系統級防護對策

     編輯:Java 相關知識

前言:安全是架構的基因

隨著電子商務與政務系統成為社會核心基礎設施,J2EE 憑藉「一次編寫,到處運行」與完善的安全體系(JCA、JSSE、JAAS 等)成為首選平台。但框架提供的機制≠業務邏輯的安全。本文梳理 J2EE 多層架構中五大高風險領域,給出經驗證的解決方案。

核心技術棧速覽

技術定位安全角色
EJB業務邏輯層事務、權限、遠程調用邊界
JAAS認證授權統一身份驗證、基於角色的訪問控制 (RBAC)
JSP/Servlet表現層輸入驗證、輸出編碼、會話管理
JDBC/JNDI資源訪問數據源隔離、連接池安全配置
JMS異步消息消息完整性、發送者身份驗證

1. Session 管理:集中存儲 + 傳輸加密

風險點

  • 客戶端存儲(Hidden Field/URL Rewriting):敏感數據暴露於瀏覽器歷史、代理日誌、網絡嗅探。
  • 服務端存儲:內存壓力大、集群需同步、Session 劫持風險。

對策

  1. 敏感業務強制 HTTPS:SSL/TLS 加密傳輸通道,防竊聽、防篡改。
  2. Session 集中存儲於中間層:避免客戶端攜帶狀態,配合分布式緩存(Redis/Memcached)解決集群同步。
  3. Session ID 安全屬性:`HttpOnly` 防 XSS 竊取,`Secure` 僅 HTTPS 傳輸,定期輪換 ID 防固定化攻擊。

2. 客戶端緩存洩露:Servlet Filter 統一攔截

瀏覽器磁盤緩存可能保留機密頁面(訂單詳情、個人信息)。最徹底的方案是 HTTP 響應頭控制:

public class CacheFilter implements Filter {
    private String cacheControlType;

    public void init(FilterConfig config) throws ServletException {
        this.cacheControlType = config.getInitParameter("CacheControlType");
        if (cacheControlType == null) throw new ServletException("缺少 CacheControlType 參數");
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        if (res instanceof HttpServletResponse) {
            HttpServletResponse resp = (HttpServletResponse) res;
            resp.addHeader("Cache-Control", cacheControlType); // no-store, no-cache, must-revalidate
            resp.addHeader("Pragma", "no-cache");
            resp.addDateHeader("Expires", 0);
        }
        chain.doFilter(req, res);
    }
    public void destroy() {}
}

web.xml 配置:映射至所有業務路徑(`/*`),參數值設為 `no-store`,確保瀏覽器不持久化任何敏感響應。

3. 視圖訪問控制:聲明式安全 + 角色隔離

防止未授權用戶直接訪問 JSP/Action,核心策略:

  • Web.xml 安全約束:定義 `` 限制 URL 模式、HTTP 方法、允許角色。
  • 虛擬角色隔離直接訪問:為內部轉發頁面創建特殊角色(如 `INTERNAL`),不分配給任何用戶。容器檢測到直接訪問缺少角色而拒絕,但 `` 內部請求不受約束。
<security-constraint>
  <web-resource-collection>
    <url-pattern>/shop/jsp/admin/*</url-pattern>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
  </web-resource-collection>
  <auth-constraint>
    <role-name>ADMIN</role-name>
  </auth-constraint>
</security-constraint>

<!-- 內部頁面僅允許虛擬角色 -->
<security-constraint>
  <web-resource-collection>
    <url-pattern>/shop/jsp/internal/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>INTERNAL</role-name> <!-- 無用戶擁有 -->
  </auth-constraint>
</security-constraint>

4. 分層耦合消除:DTO 隔離協議細節

反模式:Service 層直接接收 `HttpServletRequest`、返回 `HttpSession`,導致業務邏輯綁定 Web 協議,難以復用、測試、遷移。

正確模式:

  • Controller 層提取參數,組裝 DTO (Data Transfer Object) 或領域對象調用 Service。
  • Service 層僅依賴 POJO,返回領域模型或 DTO。
  • Domain 對象不持有任何 Servlet/JSP API 引用。

這符合《企業應用架構模式》中「數據傳輸對象」與「服務層」模式,也是 Spring MVC、Dubbo 等框架的設計基石。

5. EJB 安全加固:傳輸、訪問、消息三重防護

威脅成因對策
會話 Bean 冒充調用網絡嗅探獲取憑證全鏈路 SSL/TLS (RMI/IIOP over SSL)
實體 Bean 未授權訪問缺乏細粒度權限控制本地接口 + JAAS 授權 + 聲明式安全 (method-permission)
MDB 惡意消息注入消息來源不可信數字簽名驗證:發送端私鑰簽名,接收端公鑰驗證,包含序列號防重放

MDB 簽名驗證代碼骨架

// 發送端
Message msg = session.createTextMessage();
msg.setString("userId", userId);
msg.setString("item", item);
msg.setInt("seq", seqNum);
msg.setString("certId", certId);
String signData = userId + ":" + item + ":" + seqNum + ":" + certId;
msg.setString("signature", sign(signData, privateKey)); // 私鑰簽名
producer.send(msg);

// 接收端 (MDB onMessage)
String checkData = userId + ":" + msg.getString("item") + ":" + msg.getInt("seq") + ":" + certId;
if (!verify(checkData, msg.getString("signature"), publicKey)) {
    throw new SecurityException("簽名驗證失敗,消息被篡改或偽造");
}
// 業務處理...

6. CA 體系與證書全生命週期管理

構建企業級 PKI 體系,核心流程:

  1. Keytool 生成根密鑰對 → 提交權威 CA (VeriSign 等) 簽名 → 成為根證書。
  2. 用戶註冊時,CA 服務端:讀取根證書/私鑰 → 構建用戶證書信息 (主體、有效期、序列號、簽發者、算法) → 私鑰簽名生成用戶證書 → 下發給用戶安裝。

// 關鍵步驟:簽發用戶證書
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(caStore), storePass);
PrivateKey caPriKey = (PrivateKey) ks.getKey(alias, keyPass);
Certificate caCert = ks.getCertificate(alias);

// 提取簽發者 DN
X500Name issuer = extractIssuerDN(caCert);

// 構建用戶證書信息
X509CertInfo info = new X509CertInfo();
info.set(X509CertInfo.VALIDITY, new CertificateValidity(start, end));
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serial));
info.set(X509CertInfo.ISSUER + ".dn", issuer);
info.set(X509CertInfo.ALGORITHM_ID, new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid));
info.set(X509CertInfo.SUBJECT + ".dn", userDN);
info.set(X509CertInfo.KEY, new CertificateX509Key(userPubKey));

// 簽名生成
X509CertImpl userCert = new X509CertImpl(info);
userCert.sign(caPriKey, "SHA256withRSA"); // 建議 SHA256+RSA

最佳實踐:證書有效期 1-2 年、CRL/OCSP 廢棄檢測、私鑰 HSM 保護、自動化續簽流程。

總結:纵深防禦體系

J2EE 安全非單點修補,需構建:

  1. 傳輸層:全站 HTTPS、雙向 TLS。
  2. 應用層:JAAS 統一認證、RBAC 細粒度授權、Filter 統一輸入輸出過濾。
  3. 業務層:EJB 聲明式/程序化安全、MDB 簽名驗證、敏感操作審計日誌。
  4. 數據層:參數化查詢防注入、字段級加密、審計觸發器。
  5. 基礎設施:CA/PKI 體系、密鑰管理、安全編碼規範、定期滲透測試。

將安全內化為架構設計的核心約束,而非事後補丁,才是構建可信 J2EE 系統的正道。

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