有没有办法在 PL/SQL 中创建 'modules'?
Is there a way to create 'modules' in PL/SQL?
我正在研究创建模块(或类似概念)的方法,许多 packages/functions/procedures 将居住在其中,但我只公开了一些外观 API。
这样做的主要原因是我想限制对任何非API方法的直接访问,以促进解耦和模块化。
我正在考虑使用 db schemata 作为 'module' 系统,但 AFAIK 它不限制访问。
有什么想法吗?
创建一个用户,用那个用户编译所有packages/functions/procedures。创建第二个用户并授予少数 packages/etc 您想要提供的访问权限,并且只允许通过该用户访问(而不是直接通过所有者访问)。
类似于:
CREATE USER package_owner IDENTIFIED BY password ACCOUNT LOCK;
REVOKE CREATE SESSION FROM package_owner;
CREATE PACKAGE package_owner.your_api
PROCEDURE your_api_procedure;
END;
/
CREATE PACKAGE BODY package_owner.your_api
PROCEDURE your_api_procedure IS BEGIN NULL; END;
PROCEDURE private_procedure IS BEGIN NULL; END;
END;
/
CREATE PACKAGE package_owner.your_hidden_package
PROCEDURE your_hidden_procedure;
END;
/
CREATE PACKAGE BODY package_owner.your_hidden_package
PROCEDURE your_hidden_procedure IS BEGIN NULL; END;
END;
/
CREATE USER access_point IDENTIFIED BY password ACCOUNT UNLOCK;
GRANT CREATE SESSION TO access_point;
GRANT EXECUTE ON package_owner.your_api TO access_point;
现在您可以连接到用户 access_point
并执行 your_api
程序包但无法执行 your_hidden_package
.
另请注意,虽然 your_api
可从 access_point
用户执行,但 private_procedure
不在包规范中,因此它仅在同一包中可见。
如果您希望控制访问权限,但不一定要控制可见性,请使用 Oracle 12.1 中的 PL/SQL 白名单功能。
例如,
设置
CREATE OR REPLACE PACKAGE public_api AS
PROCEDURE p1_pub;
END;
/
CREATE OR REPLACE PACKAGE private_api
ACCESSIBLE BY (PACKAGE public_api) -- This is the key part of the feature
AS
PROCEDURE p2_pvt;
END private_api;
/
CREATE OR REPLACE PACKAGE BODY public_api AS
PROCEDURE p1_pub IS
BEGIN
private_api.p2_pvt;
END;
END public_api;
CREATE OR REPLACE PACKAGE BODY private_api AS
PROCEDURE p2_pvt IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello from private API!');
END;
END private_api;
通过 public API
测试访问
BEGIN
public_api.p1_pub;
END;
/
结果:私人问候API!
测试直接访问私有API
BEGIN
private_api.p2_pvt;
END;
/
结果: PLS-00904:访问对象的权限不足PRIVATE_API
我正在研究创建模块(或类似概念)的方法,许多 packages/functions/procedures 将居住在其中,但我只公开了一些外观 API。
这样做的主要原因是我想限制对任何非API方法的直接访问,以促进解耦和模块化。
我正在考虑使用 db schemata 作为 'module' 系统,但 AFAIK 它不限制访问。
有什么想法吗?
创建一个用户,用那个用户编译所有packages/functions/procedures。创建第二个用户并授予少数 packages/etc 您想要提供的访问权限,并且只允许通过该用户访问(而不是直接通过所有者访问)。
类似于:
CREATE USER package_owner IDENTIFIED BY password ACCOUNT LOCK;
REVOKE CREATE SESSION FROM package_owner;
CREATE PACKAGE package_owner.your_api
PROCEDURE your_api_procedure;
END;
/
CREATE PACKAGE BODY package_owner.your_api
PROCEDURE your_api_procedure IS BEGIN NULL; END;
PROCEDURE private_procedure IS BEGIN NULL; END;
END;
/
CREATE PACKAGE package_owner.your_hidden_package
PROCEDURE your_hidden_procedure;
END;
/
CREATE PACKAGE BODY package_owner.your_hidden_package
PROCEDURE your_hidden_procedure IS BEGIN NULL; END;
END;
/
CREATE USER access_point IDENTIFIED BY password ACCOUNT UNLOCK;
GRANT CREATE SESSION TO access_point;
GRANT EXECUTE ON package_owner.your_api TO access_point;
现在您可以连接到用户 access_point
并执行 your_api
程序包但无法执行 your_hidden_package
.
另请注意,虽然 your_api
可从 access_point
用户执行,但 private_procedure
不在包规范中,因此它仅在同一包中可见。
如果您希望控制访问权限,但不一定要控制可见性,请使用 Oracle 12.1 中的 PL/SQL 白名单功能。
例如,
设置
CREATE OR REPLACE PACKAGE public_api AS
PROCEDURE p1_pub;
END;
/
CREATE OR REPLACE PACKAGE private_api
ACCESSIBLE BY (PACKAGE public_api) -- This is the key part of the feature
AS
PROCEDURE p2_pvt;
END private_api;
/
CREATE OR REPLACE PACKAGE BODY public_api AS
PROCEDURE p1_pub IS
BEGIN
private_api.p2_pvt;
END;
END public_api;
CREATE OR REPLACE PACKAGE BODY private_api AS
PROCEDURE p2_pvt IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello from private API!');
END;
END private_api;
通过 public API
测试访问BEGIN
public_api.p1_pub;
END;
/
结果:私人问候API!
测试直接访问私有API
BEGIN
private_api.p2_pvt;
END;
/
结果: PLS-00904:访问对象的权限不足PRIVATE_API