PLS-00201 OS_COMMAND.EXEC未声明 Oracle存储过程授权解决方法
问题根因
你遇到的PLS-00201: ID 'OS_COMMAND.EXEC' must be declared报错和你写的foo存储过程中调用dbms_java.grant_permission的逻辑没有直接关联,该报错本质是两个问题叠加导致:
- 你当前数据库环境存在对自定义对象
OS_COMMAND.EXEC的失效依赖,这个对象不是Oracle内置组件,属于自定义的操作系统命令调用包 - 你试图在普通自定义存储过程里调用
dbms_java.grant_permission的操作本身不符合权限模型要求,该包属于SYS用户所有的系统级权限操作包,普通用户默认无调用权限,且不能通过角色继承的方式在存储过程中使用。
正确完成Java权限授予的操作步骤
不要通过普通用户自定义存储过程封装权限授予操作,直接用SYS用户执行授权命令即可,操作如下:
-- 切换到SYS用户会话下执行 BEGIN DBMS_JAVA.GRANT_PERMISSION( grantee => 'FOOBAR', permission_type => 'SYS:java.io.FilePermission', permission_name => '<<ALL FILES>>', permission_action => 'execute' ); END; / -- 授权后执行权限生效校验 EXEC DBMS_JAVA.SET_OUTPUT(2000);
如果业务必须通过存储过程完成授权操作,需要先在SYS用户下给存储过程所属用户授予直接权限(不能通过角色授予),再创建带调用者权限声明的存储过程:
-- SYS下执行,给存储过程所属用户(示例为FOOBAR用户)授予必要权限 GRANT EXECUTE ON SYS.DBMS_JAVA TO FOOBAR; GRANT ALTER USER TO FOOBAR; -- 切换到FOOBAR用户下创建存储过程 CREATE OR REPLACE PROCEDURE foo AUTHID CURRENT_USER IS BEGIN DBMS_JAVA.GRANT_PERMISSION( 'FOOBAR', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' ); END foo; /
OS_COMMAND.EXEC标识符的声明方法
OS_COMMAND.EXEC不是Oracle官方内置对象,是用来调用Java存储过程执行操作系统命令的自定义包,如果你确实需要使用该对象,需要在对应用户下手动创建包声明和关联Java实现的包体:
-- 先创建包声明 CREATE OR REPLACE PACKAGE OS_COMMAND IS FUNCTION EXEC(cmd IN VARCHAR2) RETURN NUMBER; END OS_COMMAND; / -- 创建包体,绑定Java运行时exec方法 CREATE OR REPLACE PACKAGE BODY OS_COMMAND IS FUNCTION EXEC(cmd IN VARCHAR2) RETURN NUMBER IS LANGUAGE JAVA NAME 'java.lang.Runtime.exec(java.lang.String) return int'; END OS_COMMAND; /
注意:给用户授予<<ALL FILES>>的execute权限属于极高风险操作,持有该权限的用户可以在数据库服务器上执行任意操作系统命令,生产环境严禁配置该级别的权限,必须严格限制可访问、可执行的文件路径范围。
内容的提问来源于stack exchange,提问作者hajduk
相关产品推荐
相关产品推荐

