首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 高級數據訪問控制與 Java 存儲過程實戰:BMP 主鍵生成、邏輯共享、安全審計

     編輯:Oracle 資料庫基礎

前言:存儲過程作為數據訪問網關

核心思想:**用戶無表直接權限,僅通過存儲過程訪問數據**。存儲過程以定義者權限 (AUTHID DEFINER) 運行,擁有表操作權限,實現細粒度控制:時間窗口限制、列級掩碼、審計日誌、業務規則強制執行。

一、 三大核心應用場景

1. 精細訪問控制 (細粒度安全)

  • 時間窗口:IF TO_CHAR(SYSDATE,'HH24') NOT BETWEEN '09' AND '18' THEN RAISE_APPLICATION_ERROR(-20001,'非工作時間禁止更新'); END IF;
  • 列級權限:HR 查詢薪資表時,存儲過程僅返回脫敏後數據 (CASE WHEN v$session.user = 'HR' THEN MASK(salary) ELSE salary END)。
  • 審計日誌:每次調用自動寫入 audit_log(who, when, sql_text, bind_vals),不可繞過。

2. 異構應用邏輯共享 (J2EE + Legacy)

Legacy (Forms/Reports) 與 J2EE (EJB/Spring) 同時調用同一組 PL/SQL/Java 存儲過程,Call Spec 屏蔽實現語言差異:

-- 同一邏輯,PL/SQL 與 Java 互為備選
CREATE OR REPLACE PROCEDURE calc_bonus(p_empno NUMBER, p_bonus OUT NUMBER)
AS LANGUAGE JAVA NAME 'BonusCalc.calc(int, int[])'; -- Java 實現
-- 或
CREATE OR REPLACE PROCEDURE calc_bonus(p_empno NUMBER, p_bonus OUT NUMBER) IS ... -- PL/SQL 實現
-- 調用端無感知:{call calc_bonus(?, ?)}

3. BMP Entity Bean 主鍵自動生成 (EJB 經典模式)

場景:ejbCreate() 需返回主鍵,主鍵由數據庫序列/邏輯生成。

-- Java 存儲過程:插入數據 + 獲取序列 + 返回主鍵
public class GenPK {
    public static BigDecimal insertAccount(String owner, BigDecimal bal) throws SQLException {
        try (Connection conn = DriverManager.getConnection("jdbc:default:connection:");
             CallableStatement cs = conn.prepareCall("{? = call seq_account.NEXTVAL}")) {
            cs.registerOutParameter(1, Types.NUMERIC);
            cs.execute();
            BigDecimal newId = cs.getBigDecimal(1);
            
            try (PreparedStatement ps = conn.prepareStatement(
                    "INSERT INTO accounts (id, owner, balance) VALUES (?, ?, ?)")) {
                ps.setBigDecimal(1, newId);
                ps.setString(2, owner);
                ps.setBigDecimal(3, bal);
                ps.executeUpdate();
            }
            return newId;
        }
    }
}

-- Call Spec
CREATE OR REPLACE FUNCTION insert_account(p_owner VARCHAR2, p_bal NUMBER) RETURN NUMBER
AS LANGUAGE JAVA NAME 'GenPK.insertAccount(java.lang.String, java.math.BigDecimal) return java.math.BigDecimal';
/

-- EJB ejbCreate 實現
public AccountPK ejbCreate(String ownerName, int balance) throws CreateException {
    try (Connection conn = dataSource.getConnection();
         CallableStatement cs = conn.prepareCall("{? = call insert_account(?, ?)}")) {
        cs.registerOutParameter(1, Types.NUMERIC);
        cs.setString(2, ownerName);
        cs.setBigDecimal(3, new BigDecimal(balance));
        cs.execute();
        return new AccountPK(cs.getBigDecimal(1));
    } catch (SQLException e) {
        throw new CreateException(e.getMessage());
    }
}

替代方案:JDBC 3.0 RETURN_GENERATED_KEYS

PreparedStatement ps = conn.prepareStatement(
    "INSERT INTO accounts (owner, balance) VALUES (?, ?)",
    Statement.RETURN_GENERATED_KEYS); // 或 new String[]{"ID"}
ps.setString(1, owner);
ps.setBigDecimal(2, bal);
ps.executeUpdate();
try (ResultSet rs = ps.getGeneratedKeys()) {
    if (rs.next()) return new AccountPK(rs.getBigDecimal(1));
}

對比:JDBC 方案可移植性更強 (跨數據庫);存儲過程方案性能更高 (單次往返、邏輯封裝)、支持複雜主鍵邏輯 (組合鍵、分表路由)。

二、 實施檢查清單

項目要求
權限模型表授權給存儲過程擁有者,用戶僅授予 EXECUTE ON PROCEDURE
參數化查詢存儲過程內部強制使用綁定變量,杜絕 SQL 注入
異常處理業務異常 RAISE_APPLICATION_ERROR(-20xxx, 'msg'),系統異常記錄日志後拋出
審計完整性審計表唯追加、不可刪改、定期歸檔、備份異地
版本管理存儲過程代碼納入 Git,部署走 CI/CD,保留回滾腳本

三、 總結

將存儲過程作為數據訪問網關,是 Oracle 實現「最小權限原則」「業務邏輯集中化」「異構應用解耦」的經典架構。配合 Java 存儲過程處理複雜計算/外部調用,PL/SQL 處理事務編排/數據流轉,構建安全、高性能、可維護的數據服務層。

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