ORACLE FGAC(细粒度权限控制)(转载)

ORACLE FGAC(细粒度权限控制)
http://www.itpub.net/thread-1037232-1-1.html

细粒度访问控制 (FGAC)。FGAC,也称为行级安全性,是一种可以根据数据内容限制访问的方法。针对此类要求的 Oracle 数据库解决方案称为虚拟专用数据库 (VPD),这是企业版的一个特性。数据库将根据安全性策略和会话上下文动态地更改查询。除了限制返回的行之外,您还可以屏蔽列。

可以使用存储过程创建安全性策略。此类策略通过使用存储在 Oracle 数据库中的应用程序数据的内容或上下文变量(例如用户名或 IP 地址)来限制访问。



Oracle数据库提供了一个称为细粒度访问控制(fine-grained access control,FGAC)的特性。简而言之,这种技术允许开发人员把过程嵌入数据库中,向数据库提交查询时可以修改查询。这种查询修改可用于限制客户只能接收或修改某些行。过程在运行查询时能查看是谁在运行查询,他们从哪个终端运行查询,等等,然后能适当地约束对数据的访问。利用FGAC,可以保证以下安全性,例如:

1 某类用户在正常工作时间之外执行的查询将返回0条记录。

2 如果终端在一个安全范围内,可以向其返回所有数据,但是远程客户终端只能得到不敏感的信息。

--主要完成ORACLE fine-grained access control , 以及使用存储过程进行权限封装
/*Oracle fine-grained access control 可以实现数据库对象行级别的权限控制 以下测试表为例: manager 只可以更改自己的 employee的行, 而不可以更改其它mananger 所拥有的employee 的行 */


CONNECT system/yJdg2U1v AS sysdba

--授予HR权限
GRANT CONNECT,RESOURCE,UNLIMITED TABLESPACE,CREATE ANY CONTEXT, CREATE PROCEDURE,
CREATE ANY TRIGGER TO HR IDENTIFIED BY HR;

CONNECT hr/hr;


--创建两张测试表
CREATE TABLE Directory (Empno NUMBER(4) NOT NULL,
Mgrno NUMBER(4) NOT NULL,
Rank NUMBER(7,2) NOT NULL);


CREATE TABLE Payroll (Empno NUMBER(4) NOT NULL,
Name VARCHAR(30) NOT NULL );


--插入测试数据
INSERT INTO Directory VALUES (1, 1, 1.0);
INSERT INTO Payroll VALUES (1, 'KING');
INSERT INTO Directory VALUES (2, 1, 5);
INSERT INTO Payroll VALUES (2, 'CLARK');



--创建序列
CREATE SEQUENCE Empno_seq START WITH 5;

CREATE SEQUENCE Rank_seq START WITH 100;

--创建上下文
CREATE OR REPLACE CONTEXT Hr_app USING Hr.Hr0_pck;
CREATE OR REPLACE CONTEXT Hr_sec USING Hr.Hr1_pck;


--创建上下文用包
CREATE OR REPLACE PACKAGE Hr0_pck IS
   PROCEDURE adjustrankby1(Empno NUMBER);
END;

-- 这一步仅仅进行了简单的测试, 并没有做过多的是设置, 可根据具体情况来设置
CREATE OR REPLACE PACKAGE BODY Hr0_pck IS
   PROCEDURE Adjustrankby1(Empno NUMBER) IS
Stmt VARCHAR2(100);
   BEGIN
DBMS_SESSION.SET_CONTEXT('hr_app', 'adjstate', 1);
   END;
END;


---
CREATE OR REPLACE PACKAGE hr1_pck IS
   PROCEDURE setid;
END;


CREATE or REPLACE PACKAGE BODY Hr1_pck IS
   PROCEDURE setid IS
id NUMBER;
   BEGIN
SELECT Empno
   INTO id
   FROM Payroll
    WHERE Name = SYS_CONTEXT('userenv', 'session_user');
DBMS_SESSION.SET_CONTEXT('hr_sec', 'empno', id);
DBMS_SESSION.SET_CONTEXT('hr_sec', 'appid', id);
   EXCEPTION
WHEN NO_DATA_FOUND THEN
   INSERT INTO Payroll
       (Empno, Name)
   VALUES
       (Empno_seq.NEXTVAL, SYS_CONTEXT('userenv', 'session_user'));
   INSERT INTO Directory
       (Empno, Mgrno, Rank)
   VALUES
       (Empno_seq.CURRVAL, 2, Rank_seq.NEXTVAL);
   SELECT Empno
       INTO id
       FROM Payroll
   WHERE Name = sys_context('userenv', 'session_user');
   DBMS_SESSION.SET_CONTEXT('hr_sec', 'empno', id);
   DBMS_SESSION.SET_CONTEXT('hr_sec', 'appid', id);
WHEN OTHERS THEN
   NULL;
   END;
END;


GRANT EXECUTE ON Hr1_pck TO public;
CONNECT system/yJdg2U1v AS sysdba

---创建logon 触发器
CREATE OR REPLACE TRIGGER Databasetrigger
   AFTER LOGON ON DATABASE
BEGIN
--- 当用户登陆时会执行 hr.Hr1_pck.Setid这个过程来完成设置上下文
hr.Hr1_pck.Setid;
END;


CONNECT hr/hr

-- 这个过程为测试过程, 并非关键步骤
CREATE OR REPLACE PACKAGE hr2_pck IS
   FUNCTION Findmgr(Empno NUMBER) RETURN NUMBER;
END;

CREATE OR REPLACE PACKAGE BODY hr2_pck IS
   /* insert a new employee record: */
   FUNCTION findmgr(empno number) RETURN NUMBER IS
Mgrid NUMBER;
   BEGIN
SELECT mgrno INTO mgrid FROM directory WHERE mgrid = empno;
RETURN mgrid;
   END;
END;


-- 创建细粒度访问策略用函数
CREATE OR REPLACE FUNCTION secure_updates(ns varchar2,na varchar2)
RETURN VARCHAR2 IS
Results VARCHAR2(100);
BEGIN
IF (sys_context('hr_app','adjstate') = 1)
THEN results := 'mgrno = SYS_CONTEXT('||'''hr_sec'',''empno'')';
ELSE results := '1=2';
END IF;
RETURN Results;
END;
/* 此过程可理解为:当一个session 发出一条sql 命令时候 会通过此过程来改变“谓语动词”,实际上就是 增加了where 条件, 比如: update hr.directory set rank=5, 那么它会根据不同的权限来改写这个条件, 比如改写为:
update hr.directory set rank=5 where mgrno = SYS_CONTEXT('hr_sec', 'empno')
/*

CONNECT system/yJdg2U1v ASsysdba;

---设置细粒度访问权限策略
BEGIN
DBMS_RLS.ADD_POLICY('hr', 'directory', 'secure_update', 'hr', 'secure_updates', 'update',true,true);
END;
-- 此策略类型为update , 还有select ,insert 等类型




--以下为测试过程:
SQL> conn hr/hr;
已连接。

SQL> select * from payroll;

    EMPNO NAME
---------- ------------------------------
       25 SYSMAN
       26 SYS
       27 HR
      1 KING
      2 CLARK


SQL> select * from directory;

    EMPNO    MGRNO    RANK
---------- ---------- ----------
       27       2        122
       26       2       10
      1       1       10
      2       1       10
--- 登陆触发器已经触发
SQL> update hr.directory set rank=10;

已更新0行。

--- 不允许更改数据

SQL> select sys_context('hr_app','adjstate') from dual;

SYS_CONTEXT('HR_APP','ADJSTATE')
-----------------------------------------------------------------------

-- 设置hr_app 上下文:

SQL> begin
   2   Hr0_pck.Adjustrankby1(100);
   3   end;
   4   /

PL/SQL 过程已成功完成。
SQL> select sys_context('hr_app','adjstate') from dual;

SYS_CONTEXT('HR_APP','ADJSTATE')
-------------------------------------------------------------

1

SQL> update directory set rank=10;

已更新0行。

-- 同样不让更新数据

-- 继续测试:

--创建clark 用户

SQL> create user clark identified by clark;

用户已创建。

SQL> grant dba ,resource,connect to clark;

授权成功。

SQL> conn clark/clark;
已连接。
SQL> select sys_context('hr_app','adjstate') from dual;

SYS_CONTEXT('HR_APP','ADJSTATE')
-----------------------------------------------------------------------



SQL> update hr.directory set rank=10;

已更新0行。

SQL> begin
   2   hr.Hr0_pck.Adjustrankby1(100);
   3   end;
   4   /

PL/SQL 过程已成功完成。

SQL>   select sys_context('hr_app','adjstate') from dual;

SYS_CONTEXT('HR_APP','ADJSTATE')
-----------------------------------------------------------------------

1

SQL> update hr.directory set rank=10;

已更新2行。

SQL> commit;

提交完成。

SQL> select * from hr.directory;

    EMPNO    MGRNO    RANK
---------- ---------- ----------
       27       2       10
       26       2       10
      1       1       10
      2       1       10

SQL> update hr.directory set rank=111;

已更新2行。

SQL> commit;

提交完成。



SQL> select * from hr.directory;

    EMPNO    MGRNO    RANK
---------- ---------- ----------
       27       2        111
       26       2        111
      1       1       10
      2       1       10

SQL>


SQL> conn / as sysdba
已连接。
SQL> set wrap off
SQL> create user king identified by king;

用户已创建。

SQL> grant dba,connect,resource to king;

授权成功。

SQL> conn king/king;
已连接。
SQL> update hr.directory set rank=20;

已更新0行。

SQL> begin
   2   hr.Hr0_pck.Adjustrankby1(100);
   3   end;
   4   /

PL/SQL 过程已成功完成。

SQL> update hr.directory set rank=20;

已更新2行。

SQL> commit;

提交完成。

SQL> select * from hr.directory;

    EMPNO    MGRNO    RANK
---------- ---------- ----------
       27       2        111
       26       2        111
      1       1       20
      2       1       20

SQL>

SQL> create user kkk identified by kkk;

用户已创建。

SQL> grant dba ,connect,resource to kkk;

授权成功。

SQL> conn kkk/kkk;
已连接。
SQL> show user;
USER 为 "KKK"
SQL> begin
   2   hr.Hr0_pck.Adjustrankby1(100);
   3   end;
   4   /

PL/SQL 过程已成功完成。

SQL> update hr.directory set rank=1;

已更新0行。

SQL> select * from hr.directory ;

    EMPNO    MGRNO    RANK
---------- ---------- ----------
       27       2        111
       26       2        111
       28       2        123
      1       1       20
      2       1       20

SQL>


/*ORACLE的细粒度权限访问控制在某些特殊安全要求下确实表现的很出色, 也可以节省大量的代码时间以及代码的维护量*/

转载地址:http://hi.baidu.com/dba_james/blog/item/327b9d1fff358718403417bb.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/110321/viewspace-608678/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/110321/viewspace-608678/

你可能感兴趣的:(ORACLE FGAC(细粒度权限控制)(转载))