SYS_CONTEXT 基本語法
SYS_CONTEXT(namespace, attribute [, length])
- namespace:命名空間 (如
USERENV、自訂)
- attribute:屬性名稱
- length:回傳值最大長度 (1~4000,預設 256)
- 回傳
VARCHAR2,Session 級別屬性
內建 USERENV 命名空間完整屬性表
| 屬性 | 說明 | 範例值 | 長度 |
SESSION_USER | 當前驗證使用者 | SCOTT | 30 |
SESSION_USERID | 當前使用者 ID | 123 | 30 |
CURRENT_USER | 當前權限擁有者 (Definer's Rights 為擁有者) | SYS | 30 |
CURRENT_USERID | 當前權限擁有者 ID | 0 | 30 |
PROXY_USER | Proxy 連線使用者 | APP_USER | 30 |
PROXY_USERID | Proxy 使用者 ID | 456 | 30 |
ISDBA | 是否啟用 DBA 角色 | TRUE/FALSE | 30 |
AUTHENTICATION_TYPE | 驗證類型 | DATABASE, OS, NETWORK, PROXY | 30 |
AUTHENTICATION_DATA | 驗證資料 (X.509 憑證 HEX) | ... | 256/4000 |
TERMINAL | 客戶端終端機識別 | WORKSTATION1 | 54 |
HOST | 客戶端主機名 | db-server-01 | 54 |
IP_ADDRESS | 客戶端 IP | 192.168.1.100 | 30 |
NETWORK_PROTOCOL | 網路協定 | TCP | 256 |
LANGUAGE | 語言_地區.字元集 | AMERICAN_AMERICA.AL32UTF8 | 52 |
LANG | ISO 語言縮寫 | US | 62 |
NLS_TERRITORY | 地區設定 | AMERICA | 62 |
NLS_CURRENCY | 貨幣符號 | $ | 62 |
NLS_CALENDAR | 行曆類型 | GREGORIAN | 62 |
NLS_DATE_FORMAT | 日期格式 | YYYY-MM-DD | 62 |
NLS_DATE_LANGUAGE | 日期語言 | AMERICAN | 62 |
NLS_SORT | 排序基礎 | BINARY | 62 |
DB_NAME | 資料庫名稱 | ORCL | 30 |
DB_DOMAIN | 資料庫網域 | example.com | 256 |
INSTANCE | 執行個體編號 | 1 | 30 |
INSTANCE_NAME | 執行個體名稱 | orcl | 30 |
SERVER_HOST | 伺服器主機名 | db-server-01 | 54 |
MODULE | 應用模組名 (DBMS_APPLICATION_INFO) | OrderEntry | 64 |
ACTION | 應用動作名 | InsertOrder | 64 |
CLIENT_INFO | 用戶端資訊 (64 bytes) | user_session_123 | 64 |
ENTRYID | 稽核項目 ID | 12345 | 30 |
SESSIONID | 稽核 Session ID | 98765 | 30 |
FG_JOB_ID | 前景作業 ID | 123 | 30 |
BG_JOB_ID | 背景作業 ID | NULL | 30 |
EXTERNAL_NAME | 外部名稱 (SSL 憑證 DN) | CN=Scott,O=Oracle | 256 |
一鍵查詢所有 USERENV 屬性
SELECT
SYS_CONTEXT('USERENV','SESSION_USER') AS session_user,
SYS_CONTEXT('USERENV','SESSION_USERID') AS session_userid,
SYS_CONTEXT('USERENV','CURRENT_USER') AS current_user,
SYS_CONTEXT('USERENV','CURRENT_USERID') AS current_userid,
SYS_CONTEXT('USERENV','PROXY_USER') AS proxy_user,
SYS_CONTEXT('USERENV','ISDBA') AS isdba,
SYS_CONTEXT('USERENV','AUTHENTICATION_TYPE') AS auth_type,
SYS_CONTEXT('USERENV','TERMINAL') AS terminal,
SYS_CONTEXT('USERENV','HOST') AS host,
SYS_CONTEXT('USERENV','IP_ADDRESS') AS ip_address,
SYS_CONTEXT('USERENV','NETWORK_PROTOCOL') AS net_protocol,
SYS_CONTEXT('USERENV','LANGUAGE') AS language,
SYS_CONTEXT('USERENV','DB_NAME') AS db_name,
SYS_CONTEXT('USERENV','INSTANCE') AS instance,
SYS_CONTEXT('USERENV','MODULE') AS module,
SYS_CONTEXT('USERENV','ACTION') AS action
FROM dual;
應用場景:SQL 注入環境偵測
攻擊者常注入 SYS_CONTEXT('USERENV','...') 探測環境:
-- 偵測是否為 DBA
' OR SYS_CONTEXT('USERENV','ISDBA')='TRUE' --
-- 取得資料庫名稱
' || SYS_CONTEXT('USERENV','DB_NAME') || '
-- 取得 IP 判斷內外網
' || SYS_CONTEXT('USERENV','IP_ADDRESS') || '
防禦措施
- 參數化查詢:使用 Bind Variable,杜絕字串拼接
- 最小權限帳號:應用使用非 DBA 帳號,
ISDBA=FALSE
- 審計 SYS_CONTEXT 存取:
AUDIT EXECUTE ON SYS.SYS_CONTEXT BY ACCESS
- WAF/資料庫防火牆:攔截含 SYS_CONTEXT 的異常查詢
- 限制 USERENV 敏感屬性:自訂 Context 替代、或使用 VPD 隱藏
自訂 Context 實戰
-- 1. 建立 Context 命名空間
CREATE OR REPLACE CONTEXT app_ctx USING app_ctx_pkg;
-- 2. 建立管理套件
CREATE OR REPLACE PACKAGE app_ctx_pkg IS
PROCEDURE set_tenant(p_tenant_id NUMBER);
PROCEDURE clear_tenant;
END;
/
CREATE OR REPLACE PACKAGE BODY app_ctx_pkg IS
PROCEDURE set_tenant(p_tenant_id NUMBER) IS
BEGIN
DBMS_SESSION.SET_CONTEXT('APP_CTX', 'TENANT_ID', p_tenant_id);
END;
PROCEDURE clear_tenant IS
BEGIN
DBMS_SESSION.CLEAR_CONTEXT('APP_CTX', 'TENANT_ID');
END;
END;
/
-- 3. 使用 (VPD/RLS 政策中)
CREATE FUNCTION tenant_policy(p_schema VARCHAR2, p_obj VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN 'tenant_id = ' || SYS_CONTEXT('APP_CTX', 'TENANT_ID');
END;
/
-- 4. 應用登入時設定
BEGIN
app_ctx_pkg.set_tenant(123);
END;
/
效能與限制
- 快取機制:Session 內多次呼叫同屬性極快
- 並行查詢限制:PX 從程序無法存取 Session Context
- RAC 環境:Context 為 Instance 級,跨節點需同步
- 長度限制:單屬性 4000 bytes,總大小受
SESSION_CONTEXT_SIZE 限制
常見錯誤
| 錯誤 | 原因 | 解決 |
| ORA-01403: no data found | Context 未設定該屬性 | 檢查 SET_CONTEXT 是否執行、命名空間正確 |
| ORA-01031: insufficient privileges | 無 CREATE CONTEXT 權限 | GRANT CREATE CONTEXT TO user |
| 回傳 NULL | 屬性名拼錯、大小寫 (不區分大小寫但建議大寫) | 核對 USERENV 拼寫 |
| 截斷 | 超過 length 參數或預設 256 | 明確指定 length => 4000 |