10g 僅有包執行權限開關,11g 引入 **XML DB ACL** 機制,控制:
錯誤範例:`ORA-24247: network access denied by access control list (ACL)`
SELECT * FROM dba_network_acls; SELECT * FROM dba_network_acl_privileges; SELECT username FROM dba_users WHERE username LIKE '%ITS%';
BEGIN
-- 1. 建立 ACL 文件
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(
acl => 'utl_http.xml', -- ACL 檔名
description => 'HTTP Access', -- 描述
principal => 'ITS', -- 授權用戶 (大小寫敏感!)
is_grant => TRUE,
privilege => 'connect', -- 權限:connect / resolve
start_date => NULL,
end_date => NULL
);
-- 2. 增加 resolve 權限 (域名解析)
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
acl => 'utl_http.xml',
principal => 'ITS',
is_grant => TRUE,
privilege => 'resolve',
start_date => NULL,
end_date => NULL
);
-- 3. 指派 ACL 給目標主機:端口範圍
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(
acl => 'utl_http.xml',
host => '100.1.2.1', -- IP 或域名 (勿用 localhost)
lower_port => 9000, -- 起始端口
upper_port => NULL -- 結束端口 (NULL=所有)
);
COMMIT;
END;
/
-- 可多次呼叫 ASSIGN_ACL 授權多主機/端口
BEGIN
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(
acl => 'utl_http.xml',
host => '10.100.49.138',
lower_port => 80,
upper_port => NULL
);
COMMIT;
END;
/
```
測試驗證
SELECT UTL_HTTP.REQUEST('https://100.1.2.1:9000/hello?wsdl') FROM dual;
-- 若報 "no listener" 確認 host 填寫 IP 而非 localhost
移除 ACL 與權限
-- 1. 撤銷主機指派
BEGIN
DBMS_NETWORK_ACL_ADMIN.UNASSIGN_ACL(
acl => 'utl_http.xml',
host => '100.1.2.1',
lower_port => 9000,
upper_port => NULL
);
END;
/
-- 2. 刪除用戶特定權限
BEGIN
DBMS_NETWORK_ACL_ADMIN.DELETE_PRIVILEGE(
acl => 'utl_http.xml',
principal => 'ITS',
is_grant => TRUE,
privilege => 'resolve'
);
END;
/
-- 3. 刪除整個 ACL 文件
BEGIN
DBMS_NETWORK_ACL_ADMIN.DROP_ACL(acl => 'utl_http.xml');
END;
/
```
關鍵注意事項
| 項目 | 說明 |
|---|---|
| 用戶名大小寫 | `principal` 必須與 `DBA_USERS.USERNAME` 完全一致 (通常大寫) |
| Host 填寫 | 建議用 **IP 地址**,域名需確保 DNS 可解析;**不可用 localhost** (指向資料庫服務器本機) |
| 端口範圍 | `lower_port`/`upper_port` 為 NULL 表示所有端口 |
| 權限類型 | `connect` (建立連線)、`resolve` (域名解析) 通常需同時授予 |
| 提交 | 每個 PL/SQL 區塊結束需 `COMMIT` 生效 |
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '100.1.2.1',
lower_port => 9000,
upper_port => 9000,
ace => XS$ACE_TYPE(
privilege_list => XS$NAME_LIST('connect', 'resolve'),
principal_name => 'ITS',
principal_type => XS_ACL.PTYPE_DB
)
);
END;
/
-- 無需預先建立 ACL 文件,單條語句完成