怎么利用Oracle的ACCESSIBLE BY子句限制包内子程序的访问权限

雨丽君_5553

雨丽君_5553

2026-09-17

691人浏览

原创

accessible by仅在编译期限制指定程序单元调用包内子程序,不控制运行时表访问或权限;必须写在包规范的子程序声明末尾,白名单需带类型前缀且引用对象须已存在有效。

怎么利用oracle的accessible by子句限制包内子程序的访问权限

ACCESSIBLE BY能限制谁调用包里的函数或过程,但不能限制表访问

ACCESSIBLE BY不是权限控制机制,它只做编译期检查:当某个程序单元(比如另一个包、过程或函数)试图调用当前包中被标记的子程序时,如果调用方不在白名单里,CREATE OR REPLACE PACKAGE就会报错 PLS-00904: insufficient privilege to access object。它不干预运行时行为,也不影响SELECT/INSERT等DML权限——那些还得靠GRANT/REVOKE。

常见错误现象是以为加了ACCESSIBLE BY就能防止别人查数据,结果发现用户照样能绕过包直接查底层表;或者误以为它能替代EXECUTE权限,导致调用方明明有EXECUTE,却因不在白名单里而编译失败。

使用场景很明确:你有一组内部工具函数(比如log_errorvalidate_input),只希望被特定业务包(如pkg_order_process)调用,不希望被任意匿名块、SQL*Plus脚本或第三方应用误用。

  • ACCESSIBLE BY必须写在子程序声明处,不能放在包体实现里
  • 白名单只接受程序单元名,不支持角色、用户或通配符(比如不能写ACCESSIBLE BY ROLE app_developer
  • 被引用的程序单元必须已存在且状态为VALID;若先创建带ACCESSIBLE BY的包,再建白名单里的包,会编译失败
  • 该子句对PACKAGE SPECIFICATION生效,与包体是否定义无关;即使包体为空,只要spec里声明了带ACCESSIBLE BY的过程,检查就起作用

怎么写ACCESSIBLE BY语句才不会编译报错

语法上容易踩坑的地方集中在位置、拼写和依赖顺序。最常出错的是把ACCESSIBLE BY写在包体里,或写成ACCESSIBLE BY (pkg_a, pkg_b)漏掉PACKAGE关键字。

正确写法必须满足三个硬性条件:

  • 只能出现在package specification中的子程序声明行末尾,例如:FUNCTION get_tax_rate RETURN NUMBER ACCESSIBLE BY (PACKAGE pkg_finance);
  • 括号内每个条目必须带类型前缀:PACKAGE pkg_namePROCEDURE proc_nameFUNCTION func_name,不能省略
  • 如果白名单含多个单元,用逗号分隔,但结尾不能有逗号(Oracle 21c仍不支持尾随逗号)
  • 被引用的pkg_finance必须已存在,且其spec已编译成功;否则当前包编译时会提示PLS-00302: component 'PKG_FINANCE' must be declared

示例(合法):

Full access to all Exchange 2010 EWS functions, should work with other EWS Open Source
Full access to all Exchange 2010 EWS functions, should work with other EWS Open Source

可完全访问 Exchange 2010 EWS,管理邮件、文件夹、附件、日历事件、联系人、任务及外出设置。

下载
CREATE OR REPLACE PACKAGE pkg_utils AS
  FUNCTION sanitize_input(p_str VARCHAR2) RETURN VARCHAR2 
    ACCESSIBLE BY (PACKAGE pkg_order_entry, PROCEDURE legacy_loader);
  PROCEDURE log_audit(p_action VARCHAR2) 
    ACCESSIBLE BY (PACKAGE pkg_audit_trail);
END;

ACCESSIBLE BY和调用者权限(AUTHID CURRENT_USER)混用时的坑

两者解决的问题不同,但叠加使用时容易产生误解。ACCESSIBLE BY管“谁能声明调用”,AUTHID CURRENT_USER管“执行时以谁的权限查表”。如果一个函数同时用了ACCESSIBLE BY (PACKAGE pkg_x)AUTHID CURRENT_USER,那意味着:只有pkg_x能编译期声明调用它,但运行时查表权限仍取决于调用者(即pkg_x的owner)是否有对应表权限。

典型问题:

  • 你给pkg_x授了SELECT ON hr.employees,但它调用的pkg_utils.sanitize_input又去查hr.departments——哪怕sanitize_input加了ACCESSIBLE BY,也拦不住权限缺失导致的运行时报错ORA-00942: table or view does not exist
  • 如果pkg_utils本身用AUTHID DEFINER(默认),而pkg_x没被授EXECUTE,那么即使ACCESSIBLE BY放行,调用仍失败,错误是ORA-06550: line X, column Y: PLS-00201: identifier 'PKG_UTILS.SANITIZE_INPUT' must be declared(因为根本看不到这个函数)
  • ACCESSIBLE BY不阻止动态SQL:如果pkg_x里用EXECUTE IMMEDIATE 'BEGIN pkg_utils.sanitize_input(...); END;',编译期检查会被绕过,ACCESSIBLE BY完全失效

为什么ACCESSIBLE BY无法防止DBA绕过

这是设计使然,不是缺陷。Oracle明确文档指出:ACCESSIBLE BY仅用于开发阶段的逻辑隔离,不提供安全边界。任何具有ADMINISTER DATABASE TRIGGERALTER ANY PROCEDURE权限的用户(通常是DBA)都能直接修改包spec,删掉ACCESSIBLE BY子句,或者把白名单加上自己的调试包。

更关键的是,它不防对象级访问。比如你有一个函数get_salaryACCESSIBLE BY (PACKAGE pkg_hr)保护,但DBA完全可以:

  • SELECT get_salary(...) FROM dual直接调用(只要他有EXECUTE权限)
  • dba_source拿到函数逻辑,然后抄一份去掉ACCESSIBLE BY重新创建
  • DBMS_DDL.CREATE_WRAPPED包裹后创建,虽然源码不可读,但调用限制依然消失

真正需要强访问控制的场景,应组合使用:显式GRANT EXECUTE + ACCESSIBLE BY作为第一道提醒,再配合审计策略(AUDIT EXECUTE ON pkg_utils)追踪非常规调用。别把它当成锁保险柜的密码。

相关专题

更多
oracle清空表数据
oracle清空表数据

当表中的数据不需要时,则应该删除该数据并释放所占用的空间。本专题为大家提供oracle清空表数据的相关文章,帮助大家解决该问题。

2023.08.16

801

5

Oracle中declare的使用
Oracle中declare的使用

Oracle DECLARE语句是PL/SQL编程语言中用于声明变量、常量、游标或异常的关键字。它的主要作用是在程序中定义这些对象,以便在后续的代码中使用。DECLARE语句的语法简单明了,可以根据需要声明多个对象。通过使用这些声明的对象,可以进行各种操作,如计算、查询数据库、处理异常等 。

2023.09.15

2193

5

oracle怎么分页
oracle怎么分页

实现分页的步骤:1、使用ROWNUM进行分页查询;2、在执行查询之前进行设置分页参数;3、使用"COUNT(*)"函数来获取总行数,并使用"CEIL"函数来向上取整计算总页数;4、在外部查询中使用"WHERE"子句来筛选出特定的行号范围,以实现分页查询。想了解更多oracle怎么分页的文章,可以来阅读本专题先的文章。

2023.09.18

2210

5

Oracle查看表操作历史记录
Oracle查看表操作历史记录

查看操作历史记录的方法:1、使用Oracle内置的审计功能,可以记录数据库中发生的各种操作,包括登录、DDL语句、DML语句等;2、使用Oracle日志文件,其中包含了数据库中发生的各种操作,可以通过查看日志文件来获取操作历史记录;3、使用Oracle的Flashback功能,可以查看数据库在某个时间点的操作历史记录;4、使用第三方工具等。本专题还提供其他查看表操作的文章,大家可以免费阅读。

2023.09.19

1289

3

Oracle中RAC的用法
Oracle中RAC的用法

Oracle中RAC的用法:1、通过在多个服务器上运行数据库实例来提供高可用性;2、允许在需要时增加或减少节点数量;3、通过将工作负载分布到多个节点上来实现负载均衡;4、使用共享存储来实现多个节点之间的数据共享;5、允许多个节点同时处理数据库请求,从而实现并行处理;6、提供了透明故障切换功能;7、使用了一些技术来确保数据的一致性;8、提供了管理工具来简化RAC环境的管理和维护。本专题还提供RAC相关的其他文章,大家可以免费阅读。

2023.09.19

1873

7

oracle imp
oracle imp

imp是Oracle数据库中的一个命令行工具,用于将导出的数据和对象从一个数据库实例导入到另一个数据库实例。imp命令的一般语法为“imp username/password@connect_string file=file_name [options]”。

2023.09.19

2389

4

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

3989

19

oracle通配符有哪些
oracle通配符有哪些

oracle通配符有“%”、“_”、“[]”和“[^]"。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.08

237

5

oracle四舍五入怎么操作
oracle四舍五入怎么操作

oracle四舍五入操作可以使用ROUND函数来实现,其语法为“ROUND(number, decimal_places)”,其中,number是要进行四舍五入的数值,decimal_places是指定的小数位数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.14

606

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程