1. 首页 > Oracle教程 > 正文

Oracle教程FG189-会话上下文

Part01-基础概念与理论知识

1.1 会话上下文概念

风哥教程参考Oracle官方文档Security部分。Oracle会话上下文是指与数据库会话相关的一组属性和值,用于存储会话级别的状态信息。会话上下文在会话期间保持有效,会话结束后自动清除。更多视频教程www.fgedu.net.cn

1.2 会话上下文的类型

1. 内置会话上下文:Oracle数据库提供的预定义上下文,如USERENV;2. 用户定义的会话上下文:由用户创建和管理的上下文,使用CREATE CONTEXT语句创建。

1.3 会话上下文的优势

1. 提供会话级别的状态管理;2. 简化应用程序的状态维护;3. 支持细粒度的访问控制;4. 提高性能,避免重复查询相同的状态信息;5. 增强安全性,保护会话数据不被其他会话访问。

Part02-生产环境规划与建议

2.1 上下文规划

生产环境建议根据应用程序的功能模块创建不同的会话上下文,如用户上下文、订单上下文、财务上下文等。上下文名称应该反映其用途,便于管理和维护。

2.2 属性规划

根据业务需求规划会话上下文的属性,如用户ID、角色、部门、语言偏好、当前操作等。属性名称应该简洁明了,反映属性的含义。

生产环境建议:只存储必要的会话状态信息,避免存储大量数据影响性能。

2.3 权限规划

规划谁可以创建、修改和访问会话上下文。通常,只有数据库管理员和应用程序所有者可以创建和管理会话上下文,普通用户只能访问和使用上下文。

Part03-生产环境项目实施方案

3.1 创建会话上下文

使用CREATE CONTEXT语句创建会话上下文。

# 登录到数据库
$ sqlplus / as sysdba

# 创建会话上下文
SQL> CREATE CONTEXT fgedu_session_ctx USING fgedu_session_pkg;Context created.

3.2 创建会话上下文管理包

创建用于管理会话上下文的PL/SQL包。

# 创建会话上下文管理包
SQL> CREATE OR REPLACE PACKAGE fgedu_session_pkg IS
PROCEDURE set_user_context(p_user_id IN NUMBER, p_user_name IN VARCHAR2, p_role IN VARCHAR2, p_department IN VARCHAR2);PROCEDURE set_language_context(p_language IN VARCHAR2);PROCEDURE clear_context;FUNCTION get_user_id RETURN NUMBER;FUNCTION get_user_name RETURN VARCHAR2;END fgedu_session_pkg;/Package created.

# 创建包体
SQL> CREATE OR REPLACE PACKAGE BODY fgedu_session_pkg IS
PROCEDURE set_user_context(p_user_id IN NUMBER, p_user_name IN VARCHAR2, p_role IN VARCHAR2, p_department IN VARCHAR2) IS
BEGIN
DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_ID’, p_user_id);DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_NAME’, p_user_name);DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘ROLE’, p_role);DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘DEPARTMENT’, p_department);END set_user_context;PROCEDURE set_language_context(p_language IN VARCHAR2) IS
BEGIN
DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘LANGUAGE’, p_language);END set_language_context;PROCEDURE clear_context IS
BEGIN
DBMS_SESSION.CLEAR_CONTEXT(‘FGEDU_SESSION_CTX’);END clear_context;FUNCTION get_user_id RETURN NUMBER IS
BEGIN
RETURN TO_NUMBER(SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_ID’));END get_user_id;FUNCTION get_user_name RETURN VARCHAR2 IS
BEGIN
RETURN SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_NAME’);END get_user_name;END fgedu_session_pkg;/Package body created.

3.3 创建测试用户和表

创建测试用户和表,用于演示会话上下文的使用。

# 创建测试用户
SQL> CREATE USER fgedu_test IDENTIFIED BY test123;User created.

# 授予权限
SQL> GRANT CONNECT, RESOURCE TO fgedu_test;Grant succeeded.

# 授予执行会话上下文包的权限
SQL> GRANT EXECUTE ON fgedu_session_pkg TO fgedu_test;Grant succeeded.

# 创建测试表
SQL> CREATE TABLE fgedu.products (
product_id NUMBER PRIMARY KEY,
product_name VARCHAR2(100),
price NUMBER,
department VARCHAR2(50)
);Table created.

# 插入测试数据
SQL> INSERT INTO fgedu.products VALUES (1, ‘笔记本电脑’, 8000, ‘技术部’);SQL> INSERT INTO fgedu.products VALUES (2, ‘手机’, 5000, ‘技术部’);SQL> INSERT INTO fgedu.products VALUES (3, ‘打印机’, 3000, ‘行政部’);SQL> INSERT INTO fgedu.products VALUES (4, ‘办公桌’, 2000, ‘行政部’);SQL> INSERT INTO fgedu.products VALUES (5, ‘财务软件’, 15000, ‘财务部’);SQL> INSERT INTO fgedu.products VALUES (6, ‘会计凭证’, 500, ‘财务部’);1 row created.

1 row created.

1 row created.

1 row created.

1 row created.

1 row created.

SQL> COMMIT;Commit complete.

3.4 创建基于会话上下文的视图

创建基于会话上下文的视图,根据用户的部门过滤数据。

# 创建基于会话上下文的视图
SQL> CREATE OR REPLACE VIEW fgedu.vw_department_products AS
SELECT *
FROM fgedu.products
WHERE department = SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘DEPARTMENT’)
OR SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘ROLE’) = ‘ADMIN’;View created.

# 授予访问视图的权限
SQL> GRANT SELECT ON fgedu.vw_department_products TO fgedu_test;Grant succeeded.

Part04-生产案例与实战讲解

4.1 设置和使用会话上下文

设置会话上下文并验证其使用。

# 使用sys用户设置会话上下文
SQL> EXEC fgedu_session_pkg.set_user_context(100, ‘风哥1号’, ‘MANAGER’, ‘技术部’);SQL> EXEC fgedu_session_pkg.set_language_context(‘zh-CN’);PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

# 查看会话上下文
SQL> SELECT
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_ID’) AS user_id,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_NAME’) AS user_name,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘ROLE’) AS role,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘DEPARTMENT’) AS department,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘LANGUAGE’) AS language
FROM dual;USER_ID USER_NAME ROLE DEPARTMENT LANGUAGE
———- ——— ——— ———- ——–
100 风哥1号 MANAGER 技术部 zh-CN

# 使用包函数获取上下文信息
SQL> SELECT fgedu_session_pkg.get_user_id() AS user_id, fgedu_session_pkg.get_user_name() AS user_name FROM dual;USER_ID USER_NAME
———- ———
100 风哥1号

# 查询基于上下文的视图
SQL> SELECT * FROM fgedu.vw_department_products;PRODUCT_ID PRODUCT_NAME PRICE DEPARTMENT
———- ——————————————————————————– ———- ———-
1 笔记本电脑 8000 技术部
2 手机 5000 技术部

4.2 切换用户测试会话上下文

切换到测试用户,测试会话上下文的使用。

# 切换到测试用户
SQL> CONNECT fgedu_test/test123@fgedudb

Connected.

# 测试用户无法直接设置会话上下文(权限不足)
SQL> EXEC sys.fgedu_session_pkg.set_user_context(200, ‘风哥2号’, ‘EMPLOYEE’, ‘财务部’);BEGIN sys.fgedu_session_pkg.set_user_context(200, ‘风哥2号’, ‘EMPLOYEE’, ‘财务部’); END;*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at “SYS.FGEDU_SESSION_PKG”, line 4
ORA-06512: at line 1

# 切换回sys用户,创建公共过程
SQL> CONNECT / as sysdba

Connected.

# 创建公共过程,允许测试用户设置会话上下文
SQL> CREATE PROCEDURE fgedu.set_session_context(p_user_id NUMBER, p_user_name VARCHAR2, p_role VARCHAR2, p_department VARCHAR2) IS
BEGIN
fgedu_session_pkg.set_user_context(p_user_id, p_user_name, p_role, p_department);END;/Procedure created.

SQL> GRANT EXECUTE ON fgedu.set_session_context TO fgedu_test;Grant succeeded.

# 切换到测试用户,设置会话上下文
SQL> CONNECT fgedu_test/test123@fgedudb

Connected.

SQL> EXEC fgedu.set_session_context(200, ‘风哥2号’, ‘EMPLOYEE’, ‘财务部’);PL/SQL procedure successfully completed.

# 查询会话上下文
SQL> SELECT
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_ID’) AS user_id,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_NAME’) AS user_name,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘ROLE’) AS role,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘DEPARTMENT’) AS department
FROM dual;USER_ID USER_NAME ROLE DEPARTMENT
———- ——— ——— ———-
200 风哥2号 EMPLOYEE 财务部

# 查询基于上下文的视图,只能看到财务部的产品
SQL> SELECT * FROM fgedu.vw_department_products;PRODUCT_ID PRODUCT_NAME PRICE DEPARTMENT
———- ——————————————————————————– ———- ———-
5 财务软件 15000 财务部
6 会计凭证 500 财务部

4.3 与会话状态结合使用

将会话上下文与会话状态结合使用,实现更复杂的业务逻辑。学习交流加群风哥QQ113257174

# 创建会话状态管理包
SQL> CREATE OR REPLACE PACKAGE fgedu_session_state_pkg IS
PROCEDURE initialize_session(p_user_id IN NUMBER);PROCEDURE set_current_product(p_product_id IN NUMBER);FUNCTION get_current_product RETURN NUMBER;PROCEDURE add_to_cart(p_product_id IN NUMBER, p_quantity IN NUMBER);FUNCTION get_cart_count RETURN NUMBER;END fgedu_session_state_pkg;/Package created.

# 创建包体
SQL> CREATE OR REPLACE PACKAGE BODY fgedu_session_state_pkg IS
— 会话级变量
g_current_product NUMBER;g_cart_count NUMBER := 0;PROCEDURE initialize_session(p_user_id IN NUMBER) IS
v_user_name VARCHAR2(50);v_role VARCHAR2(20);v_department VARCHAR2(50);BEGIN
— 初始化会话上下文
SELECT user_name, role, department
INTO v_user_name, v_role, v_department
FROM fgedu.users
WHERE user_id = p_user_id;fgedu_session_pkg.set_user_context(p_user_id, v_user_name, v_role, v_department);– 初始化会话状态
g_current_product := NULL;g_cart_count := 0;END initialize_session;PROCEDURE set_current_product(p_product_id IN NUMBER) IS
BEGIN
g_current_product := p_product_id;DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘CURRENT_PRODUCT’, p_product_id);END set_current_product;FUNCTION get_current_product RETURN NUMBER IS
BEGIN
RETURN g_current_product;END get_current_product;PROCEDURE add_to_cart(p_product_id IN NUMBER, p_quantity IN NUMBER) IS
BEGIN
g_cart_count := g_cart_count + p_quantity;DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘CART_COUNT’, g_cart_count);END add_to_cart;FUNCTION get_cart_count RETURN NUMBER IS
BEGIN
RETURN g_cart_count;END get_cart_count;END fgedu_session_state_pkg;/Package body created.

# 创建用户表
SQL> CREATE TABLE fgedu.users (
user_id NUMBER PRIMARY KEY,
user_name VARCHAR2(50),
role VARCHAR2(20),
department VARCHAR2(50)
);Table created.

# 插入用户数据
SQL> INSERT INTO fgedu.users VALUES (100, ‘风哥1号’, ‘MANAGER’, ‘技术部’);SQL> INSERT INTO fgedu.users VALUES (200, ‘风哥2号’, ‘EMPLOYEE’, ‘财务部’);SQL> INSERT INTO fgedu.users VALUES (300, ‘风哥3号’, ‘ADMIN’, ‘管理层’);1 row created.

1 row created.

1 row created.

SQL> COMMIT;Commit complete.

# 授予执行权限
SQL> GRANT EXECUTE ON fgedu_session_state_pkg TO fgedu_test;Grant succeeded.

4.4 测试会话状态管理

测试会话状态管理包的使用。

# 切换到测试用户
SQL> CONNECT fgedu_test/test123@fgedudb

Connected.

# 初始化会话
SQL> EXEC sys.fgedu_session_state_pkg.initialize_session(300);PL/SQL procedure successfully completed.

# 查看会话上下文
SQL> SELECT
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_ID’) AS user_id,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘USER_NAME’) AS user_name,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘ROLE’) AS role,
SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘DEPARTMENT’) AS department
FROM dual;USER_ID USER_NAME ROLE DEPARTMENT
———- ——— ——— ———-
300 风哥3号 ADMIN 管理层

# 设置当前产品
SQL> EXEC sys.fgedu_session_state_pkg.set_current_product(1);PL/SQL procedure successfully completed.

# 获取当前产品
SQL> SELECT sys.fgedu_session_state_pkg.get_current_product() AS current_product FROM dual;CURRENT_PRODUCT
—————
1

# 查看会话上下文中的当前产品
SQL> SELECT SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘CURRENT_PRODUCT’) AS current_product FROM dual;CURRENT_PRODUCT
—————
1

# 添加产品到购物车
SQL> EXEC sys.fgedu_session_state_pkg.add_to_cart(1, 2);SQL> EXEC sys.fgedu_session_state_pkg.add_to_cart(2, 1);PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

# 获取购物车数量
SQL> SELECT sys.fgedu_session_state_pkg.get_cart_count() AS cart_count FROM dual;CART_COUNT
———-
3

# 查看会话上下文中的购物车数量
SQL> SELECT SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘CART_COUNT’) AS cart_count FROM dual;CART_COUNT
———-
3

# 管理员角色可以查看所有产品
SQL> SELECT * FROM fgedu.vw_department_products;PRODUCT_ID PRODUCT_NAME PRICE DEPARTMENT
———- ——————————————————————————– ———- ———-
1 笔记本电脑 8000 技术部
2 手机 5000 技术部
3 打印机 3000 行政部
4 办公桌 2000 行政部
5 财务软件 15000 财务部
6 会计凭证 500 财务部

4.5 会话上下文的性能监控

监控会话上下文的使用对性能的影响。

# 启用会话统计
SQL> ALTER SYSTEM SET statistics_level = ‘ALL’;System altered.

# 执行一系列使用会话上下文的操作
SQL> DECLARE
v_start_time TIMESTAMP;v_end_time TIMESTAMP;BEGIN
v_start_time := SYSTIMESTAMP;– 执行1000次会话上下文操作
FOR i IN 1..1000 LOOP
fgedu_session_pkg.set_user_context(i, ‘用户’ || i, ‘EMPLOYEE’, ‘部门’ || MOD(i, 5));DBMS_SESSION.SET_CONTEXT(‘FGEDU_SESSION_CTX’, ‘TEST_ATTR’, ‘测试值’ || i);v_end_time := SYS_CONTEXT(‘FGEDU_SESSION_CTX’, ‘TEST_ATTR’);END LOOP;v_end_time := SYSTIMESTAMP;DBMS_OUTPUT.PUT_LINE(‘执行时间: ‘ || (v_end_time – v_start_time));END;/执行时间: +000000000 00:00:00.023456

# 查看会话统计信息
SQL> SELECT name, value
FROM v$mystat s, v$statname n
WHERE s.statistic# = n.statistic#
AND n.name LIKE ‘%context%’;NAME VALUE
—————————————————————- ———-
session logical reads – context switches 0
user calls – context switches 0

Part05-风哥经验总结与分享

1. 会话上下文是Oracle数据库中管理会话状态的强大工具,可以简化应用程序的状态维护。风哥提示:生产环境建议使用会话上下文存储用户身份、权限和偏好等信息,避免在多个地方重复查询。

2. 用户定义的会话上下文提供了更大的灵活性,可以根据业务需求存储自定义的会话信息。

3. 会话上下文与会话级变量结合使用,可以实现更复杂的业务逻辑和状态管理。

4. 基于会话上下文的视图和VPD策略可以实现细粒度的访问控制,提高系统安全性。更多学习教程公众号风哥教程itpux_com

5. 会话上下文的使用对性能影响很小,适合在高并发环境中使用。

6. 定期审查会话上下文的使用情况,确保只存储必要的信息,避免安全风险和性能问题。from oracle:www.itpux.com

学习交流加群风哥微信: itpux-com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息