我的主要目标是编写一个 PLSQL 程序,在给出主机、端口、服务、用户名和密码时创建数据库链接。我需要阻止创建指向同一数据库的数据库链接。如何阻止创建指向同一数据库的数据库链接,以便通知用户不允许创建指向同一数据库的数据库链接。
4 回答
确保您获得的主机和服务名称与您正在运行的数据库不同。您可以从'USERENV' 命名空间中的SYS_CONTEXT 函数获取此信息:
SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS SERVICE_NAME,
SYS_CONTEXT('USERENV', 'SERVER_HOST') AS SERVER_HOST
FROM DUAL
例如,您的过程可能如下所示:
CREATE OR REPLACE PROCEDURE CREATE_DB_LINK(pinHost IN VARCHAR2,
pinPort IN NUMBER,
pinService IN VARCHAR2,
pinUsername IN VARCHAR2,
pinPassword IN VARCHAR2)
AS
strHost VARCHAR2(100);
strService VARCHAR2(100);
BEGIN
SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME'),
SYS_CONTEXT('USERENV', 'SERVER_HOST')
INTO strService,
strHost
FROM DUAL;
IF pinHost = strHost AND
pinService = strService
THEN
RAISE_APPLICATION_ERROR(-20001, 'Cannot create link to current DB');
END IF;
-- rest of code
END CREATE_DB_LINK;
您的方法存在一个致命缺陷:使用默认调用者权限运行此过程的任何人都必须授予他们 CREATE DATABASE LINK 特权才能使过程正常工作。这将允许他们直接创建链接并完全绕过您的程序。
或者,如果创建该过程以使用所有者权限而不是默认调用者权限运行,则它将在另一个模式中创建数据库链接,用户无论如何都无法访问它,或者您必须创建公共数据库链接——一般不应该使用,只能由 DBA 创建。时期。
简而言之,整个概念是有缺陷的,无法如您所描述的那样实施。用户要么会忽略您的过程,和/或会造成安全噩梦。一般来说,我同意@EdStevens 和@MarmiteBomber 之前的评论,即数据库链接永远只能由DBA 创建。我什至会更进一步,建议应该通过使用 API 模式中的本地视图和同义词来访问链接,并且永远不要由用户直接访问。
访问数据库链接打开了一个关于大多数用户不应该访问的远程数据库的信息世界(比如 ALL_USERS 获取系统上每个有效用户帐户的列表),并且应该只作为一个的一部分正式的、版本控制的、数据模式。使用 API 通过链接提取数据可防止用户直接查询远程数据字典,并增强两个系统的安全性。
由于这是您编写的程序,因此请将该检查包含在其中。
例如,存储应该排除在表中的数据库列表(这样您就不必将它们的名称硬编码到过程中)。然后检查数据库 - 您作为参数获得的参数 - 是否被列入黑名单。如果是这样,请通知用户无法创建数据库链接。
如何?通过过程的OUT
参数,或RAISE_APPLICATION_ERROR
.
在创建数据库链接的过程中,在实际创建数据库链接之前,您可以让它检查这些视图之一。
- DBA_DB_LINKS - 数据库中定义的所有 DB 链接
- ALL_DB_LINKS - 当前用户有权访问的所有数据库链接
- USER_DB_LINKS - 当前用户拥有的所有数据库链接
如果链接已经存在于其中一个视图中,则要么引发错误,要么不再次创建它。