问题描述:

如表rm_circuit是a用户的,授予b用户select,insert,update,delete权限,在b用的存储过程中执行dbms_stats.gather_table_stats提示:ora-020000:unable to analyze table "a"."rm_circuit",insufficient privileges or does not exist.但是直接在plsql中在b用户下执行begin dbms_stats.gather_table_stats('a','rm_circuit');end;可以成功执行。如果没有权限,怎么b用户用plsql就可以执行呢

问题原因:

procedure需要显示的授权,虽然对表已经授权了,但是在过程中是无效的。

解决办法:

1、在过程中加上对表进行授权的操作;

2、在过程中加上 AUTHID CURRENT_USER 。

 

之前就接触过几次 AUTHID CURRENT_USER ,但是也没仔细的研究过。今天花了大半天时间测试测试了这个东西的使用。具体如下:

AUTHID CURRENT_USER
如果在包中或过程中加上 AUTHID CURRENT_USER 表示以调用者的身份执行。默认情况下以定义者身份执行。
定义者身份:在执行中,当前用户只有除角色权限外的权限。
调用者身份:在执行中,当前用户拥有已经授以的所有权限(包含角色权限和系统权限)。


测试1:
GWM用户拥有的角色权限和系统权限如下所示:

执行用户:gwm。分析的表:lttfm用户下的b$i_exch_info表。
1、在平常的plsql中执行如下语句,以下语句分析表成功,说明该用户即使没有显式的授权分析任何表的权限,但是由于该用户具有dba角色权限可以进行分析任何表
begin dbms_stats.gather_table_stats('lttfm','b$i_exch_info');end;--执行成功

2、用过程对表进行分析。执行失败。说明在执行过程时默认是以定义者身份执行,对于角色权限是无效的。
CREATE OR REPLACE PROCEDURE p_authiduser_test  IS
BEGIN
    dbms_stats.gather_table_stats('lttfm','b$i_exch_info');
END p_authiduser_test;

执行过程提示错误:
SQL> EXEC gwm.p_authiduser_test;
begin gwm.p_authiduser_test; end;
 
ORA-20000: Unable to analyze TABLE "LTTFM"."B$I_EXCH_INFO", insufficient privileges or does not exist
ORA-06512: 在 "SYS.DBMS_STATS", line 13046
ORA-06512: 在 "SYS.DBMS_STATS", line 13076
ORA-06512: 在 "GWM.P_AUTHIDUSER_TEST", line 6
ORA-06512: 在 line 2

3、对gwm用户授以分析任何表的权限,执行过程成功。说明定义者身份执行过程只认显式授以的权限。
grant analyze any to gwm;

SQL> EXEC gwm.p_authiduser_test;
PL/SQL procedure successfully completed

4、或者收回分析任何表权限,在过程上加上 AUTHID CURRENT_USER。执行如下过程,也可以成功执行。说明过程以调用者身份执行能够识别角色权限。
revoke analyze any from gwm;
CREATE OR REPLACE PROCEDURE p_authiduser_test AUTHID CURRENT_USER IS
BEGIN
    dbms_stats.gather_table_stats('lttfm','b$i_exch_info');
END p_authiduser_test;


测试2:以另一个用户来执行
revoke analyze any from gwm;
转到ltwebgis用户
执行如下过程无法成功执行。仍然如测试1中2的提示:
CREATE OR REPLACE PROCEDURE p_authiduser_test IS
BEGIN
    dbms_stats.gather_table_stats('lttfm','b$i_exch_info');
END p_authiduser_test;

如果对gwm授以分析任何表权限或者直接在过程中加上 AUTHID CURRENT_USER ,在ltwebgis用户下执行过程也可以成功创建表。
SQL> EXEC gwm.p_authiduser_test;
PL/SQL procedure successfully completed


测试3:测试 AUTHID CURRENT_USER 在执行过程中对操作用户的影响
测试过程:创建该过程的用户:gwm
CREATE OR REPLACE PROCEDURE p_authiduser_test IS
  v_session_user   VARCHAR2(255);
  v_current_user   VARCHAR2(255);
  v_current_schema VARCHAR2(255);
BEGIN
  SELECT sys_context('userenv', 'session_user') session_user,
         sys_context('userenv', 'current_user') current_user,
         sys_context('userenv', 'current_schema') current_schema
    INTO v_session_user, v_current_user, v_current_schema
    FROM dual;
  dbms_output.put_line('session_user:'||v_session_user);
  dbms_output.put_line('current_user:'||v_current_user);
  dbms_output.put_line('current_schema:'||v_current_schema);
  /*dbms_stats.gather_table_stats('lttfm', 'b$i_exch_info');*/
END p_authiduser_test;

gwm用户下执行该过程:
SQL> SET SERVEROUTPUT ON;
SQL>  EXEC p_authiduser_test;
session_user:GWM
current_user:GWM
current_schema:GWM

转到ltwebgis用户下执行:
SQL> SET SERVEROUTPUT ON;
SQL> EXEC gwm.p_authiduser_test;
session_user:LTWEBGIS
current_user:GWM
current_schema:GWM

修改过程如下,即加上AUTHID CURRENT_USER

CREATE OR REPLACE PROCEDURE p_authiduser_test AUTHID CURRENT_USER IS
  v_session_user   VARCHAR2(255);
  v_current_user   VARCHAR2(255);
  v_current_schema VARCHAR2(255);
BEGIN
  SELECT sys_context('userenv', 'session_user') session_user,
         sys_context('userenv', 'current_user') current_user,
         sys_context('userenv', 'current_schema') current_schema
    INTO v_session_user, v_current_user, v_current_schema
    FROM dual;
  dbms_output.put_line('session_user:'||v_session_user);
  dbms_output.put_line('current_user:'||v_current_user);
  dbms_output.put_line('current_schema:'||v_current_schema);
  /*dbms_stats.gather_table_stats('lttfm', 'b$i_exch_info');*/
END p_authiduser_test;

gwm用户下执行:
SQL> SET SERVEROUTPUT ON;
SQL>  EXEC p_authiduser_test;
session_user:GWM
current_user:GWM
current_schema:GWM

转到ltwebgis用户下执行:
SQL> SET SERVEROUTPUT ON;
SQL> EXEC gwm.p_authiduser_test;
session_user:LTWEBGIS
current_user:LTWEBGIS
current_schema:LTWEBGIS

如测试3可得出:
1、如果是本用户gwm执行,不管是否加上 AUTHID CURRENT_USER 即不管是以定义者还是调用者身份执行,其打开的会话,当前用户,当前的模式都是gwm,唯一的区别是不同身份的执行其获取的权限不同。
2、如果是用别的用户ltwebgis用户来执行,如果不加 AUTHID CURRENT_USER ,只是打开的会话用户是ltwebgis,执行过程的当前用户和当前模式都是gwm;但是如果加上 AUTHID CURRENT_USER ,则执行的时候就完全是以ltwebgis用户进行操作了,创建的表使用的表都是以ltwebgis用户所拥有的。

如下过程创建一个表:该过程是gwm用户下的。
CREATE OR REPLACE PROCEDURE p_authiduser_test AUTHID CURRENT_USER IS
BEGIN
  EXECUTE IMMEDIATE 'CREATE TABLE fyzh_test (id NUMBER,name VARCHAR2(255))';
END p_authiduser_test;
如果是gwm用户执行,不管是否加了AUTHID CURRENT_USER,创建的表都是gwm用户下的;但是如果是在ltwebgis用户执行该过程,不加
AUTHID CURRENT_USER 这个的话,执行其过程创建的表是gwm用户的(如上结论可知其执行的用户仍为gwm),如果加了 AUTHID CURRENT_USER,
创建的表就是ltwebgis用户下的(如上结论可知加上AUTHID CURRENT_USER这个,在ltwebgis用户下执行该过程其操作的用户就是ltwebgis)。

 

 随后又出现了问题:

在过程中加入AUTHID CURRENT_USER后,手动执行该过程倒是可以了,但是发现job执行仍然无法成功,仍提示没有足够的权限。

看来对于job无法识别AUTHID CURRENT_USER。没找到更好的办法,只能先显式的对用户进行授权,解决该问题。

 

 

posted on 2011-08-17 20:28  蓝紫  阅读(6638)  评论(0编辑  收藏  举报