关于SYS用户的验证


-------------------------------
SYS用户是Oracle中权限最高的用户,而SYSTEM是一个用于数据库管理的用户。在数据库安装完之后,应立即修改SYS,SYSTEM这两个用户的口令,以保证数据库的安全。可以用三种方法修改口令:
sqlplus / as sysdba;
1.sql> alter user sys identified by 11111
2.sql>grant connect to sys identified by 11111
3.sql>password system (注:此命令只适用于SYSTEM)
SYS和SYSTEM用户之间可以相互修改口令。

但是请注意,将修改完口令修改成11111后,按以下几种方法登录:
sqlplus / as sysdba;
sqlplus sys/abcde as sysdba;
sqlplus sys/ as sysdba;
sqlplus sys as sysdba;
都可以登录成功,然后查看当前用户:
sql>show user
显示 user is 'SYS'。
这是为什么呢,为什么修改了口令没有效果。
答案是:认证方法。

SYS口令认证分为操作系统认证和Oracle认证方法。
在操作系统认证方式下,对于如果是Unix操作系统,只要旧以DBA组中的用户登录的操作系统,就可以以SYSDBA的身份登录数据库,不会验证SYS的口令。
对于winnt操作系统,在oracle数据库安装后,会自动在操作系统中安装一个名为ORA_DBA的用户组,只要是该组中的用户,即可以SYSDBA的身份登录数据库而不会验证SYS的口令。也可以创建名为ORA_SID_DBA(SID为实例名)的用户组,属于该用户组的用户也可以具备以上特权。

接下说一说,如何修改认证方式为操作系统认证或oracle认证。(winnt,unix平台有大同小异)
要将认证方式设置为操作系统认证:
1.修改参数REMOTE_LOGIN_PASSWORDFILE为NONE
2.修改SQLNET.ORA文件,此文件所在目录为:.../oracle/product/10.1.0/db_1/network/admin/sqlnet.ora。在其中添加这一行:
SQLNET.AUTENTICATION_SERVICES=(NTS)
3.重新启动数据库。
要将认证方式设置为oracle认证(口令文件认证):
1.修改参数REMOTE_LOGIN_PASSWORDFILE为EXCLUSIVE或SHARED。其中,exclusive表示仅有一个实例可以使用口令文件。shared表口令文件可以供多个实例使用。
2.修改SQLNET.ORA文件,在SQLNET.AUTENTICATION_SERVICES=(NTS)前加#号,即#SQLNET.AUTENTICATION_SERVICES=(NTS)
3.重新启动数据库。
创建密码文件:
orapwd file=FILEPATH/pwd<sid>  password=PASSWORD entries=N
其中FILEPATH表示密码文件路径,密码文件的格式为pwd<sid>,sid是数据库实例名。在unix下为orapwd<sid>。

<think>我们正在处理用户的问题:sys用户如何删除其他用户的私有dblink(在Oracle数据库中) 根据提供的引用,我们可以总结出以下几点: 1. 私有dblink属于创建它的用户,其他用户无法直接删除(引用[1])。 2. 引用[2]提供了一个存储过程,使用SYS用户以其他用户的身份执行删除dblink的语句。 3. 引用[3]展示了使用DBMS_SCHEDULER创建一个作业来执行删除语句(但这里实际上是模拟其他用户执行?)。 但是,请注意,引用[2]的存储过程使用了SYS.DBMS_SYS_SQL包,这是一个内部包,通常不推荐直接使用,因为它可能不稳定且Oracle不提供支持。 另外,引用[3]的方法是通过创建一个作业,作业可以指定在哪个用户下运行(这里没有指定,但可以通过设置job的owner?)。然而,示例中创建作业时使用了'UCR_CEN8.test',但执行语句是删除一个名为UCR_CEN1_TO_CEN的dblink,这看起来可能是在UCR_CEN8用户下执行,但dblink可能属于其他用户?所以这个方法可能不直接。 因此,我们需要一个安全且推荐的方法。 实际上,作为SYS用户,我们可以使用以下方法之一: 方法1:使用存储过程(如引用[2]),但注意该包(DBMS_SYS_SQL)是内部包,不推荐使用。 方法2:使用DBMS_SCHEDULER(或DBMS_JOB)来以目标用户的身份运行删除语句。 方法3:直接使用ALTER SESSION SET CURRENT_SCHEMA = <目标用户>; 然后删除dblink?但注意,dblink并不在模式(schema)中,而是属于用户。而且,删除dblink的语法不允许用模式名限定。所以不行。 方法4:使用动态SQL,以目标用户的身份执行。但SYS用户如何模拟其他用户执行呢?可以使用“EXECUTE IMMEDIATE”加上“AS USER”子句?但是,Oracle中并没有直接支持在动态SQL中指定执行用户。 因此,比较可行的方法是使用DBMS_SCHEDULER创建一个由目标用户运行的作业,然后立即运行该作业,最后删除作业。 步骤: 1. 创建一个作业,作业的所有者(owner)设置为目标用户(schemaName),作业内容为删除dblink的语句。 2. 运行该作业。 3. 删除该作业。 但注意:创建作业需要CREATE JOB权限,而目标用户可能没有这个权限?所以我们可以以SYS用户创建作业,并指定作业的所有者为目标用户(使用SYS权限可以做到)。 引用[3]中的示例: exec dbms_scheduler.create_job(job_name=>'UCR_CEN8.test', job_type=>'PLSQL_BLOCK', job_action=>'BEGIN execute immediate ''drop database link UCR_CEN1_TO_CEN'';END;'); 但是,这个示例中,作业的所有者是谁?它没有明确指定,默认可能是当前用户SYS)。那么执行作业时,是以作业的所有者身份执行的。所以我们需要将作业的所有者设置为目标用户。 然而,在创建作业时,我们可以通过设置属性`job_style=>'REGULAR'`(默认)和指定`owner`(在`create_job`过程中,我们可以指定作业的所有者)?但是查看DBMS_SCHEDULER的文档,create_job过程并没有直接指定所有者的参数。实际上,作业的所有者就是创建作业的用户,除非使用`CREATE ANY JOB`权限来为其他用户创建作业。 因此,我们可以这样: - 使用SYS用户(具有CREATE ANY JOB权限)创建一个作业,作业名可以指定为"[目标用户].作业名",这样作业就属于目标用户了。 - 然后设置作业的内容为删除dblink的语句。 具体步骤: 1. 构建作业名:'[目标用户].JOB_DROP_DBLINK'(注意,作业名必须唯一,且目标用户必须存在)。 2. 创建作业,类型为PLSQL_BLOCK,作业动作为删除dblink的语句。 3. 设置作业立即运行。 4. 等待作业完成(或检查状态)。 5. 删除作业。 示例代码(PL/SQL块): ``` BEGIN DBMS_SCHEDULER.CREATE_JOB( job_name => '目标用户.JOB_DROP_DBLINK_TEMP', -- 例如:'SCOTT.DROP_MY_DBLINK' job_type => 'PLSQL_BLOCK', job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK 你的DBLINK名称''; END;', enabled => TRUE, -- 创建后立即启用 auto_drop => TRUE -- 作业完成后自动删除 ); -- 由于启用了auto_drop,作业运行后会自动删除,所以我们不需要再手动删除。 -- 但是,作业可能不会立即运行,所以我们可以让它运行后等待一下。 -- 如果需要确保立即执行,可以创建后启用,然后等待。 END; / ``` 注意:这里的dblink名称需要替换,目标用户需要替换,作业名可以自定义(但必须唯一,且符合命名规则)。 但是,这种方法有一个问题:如果作业执行失败,我们可能无法立即知道,而且作业会自动删除(因为设置了auto_drop)。所以,我们可以不设置auto_drop,然后手动检查并删除。 另外,如果dblink名称包含小写或特殊字符,需要使用双引号括起来,在动态SQL中要注意转义。 例如,要删除的dblink名为"my_link",则语句应为:`DROP DATABASE LINK "my_link"` 在作业动作中,我们需要这样写: job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "my_link"''; END;' 或者,如果dblink名称是大写的,且创建时没有用双引号,那么直接写大写即可。 方法5:使用SYS用户直接删除?但Oracle不允许,因为私有dblink属于特定用户。除非使用上面提到的内部包(不推荐)。 综合考虑,使用DBMS_SCHEDULER是相对安全且官方支持的方法。 但是,请注意权限:SYS用户有足够的权限创建其他用户的作业。 因此,我们给出使用DBMS_SCHEDULER的步骤: 1. 以SYS用户登录。 2. 执行以下PL/SQL块,将`schema_name`替换为拥有dblink的用户名,将`dblink_name`替换为要删除的dblink名称(注意大小写和引号)。 示例: ``` BEGIN -- 创建作业,作业名由目标用户和自定义作业名组成 DBMS_SCHEDULER.CREATE_JOB( job_name => '"' || schema_name || '"."JOB_DROP_DBLINK_' || TO_CHAR(SYSTIMESTAMP, 'YYYYMMDDHH24MISSFF') || '"', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK ' || -- 如果dblink名称中有小写或特殊字符,需要加双引号,这里假设dblink名称是标准的大写(不加引号) -- 为了安全,我们可以将dblink名称用双引号括起来,并处理其中的双引号(将每个双引号替换成两个双引号) -- 但更简单的方式是:如果dblink名称是大小写敏感的,那么创建时用了双引号,删除时也要用双引号。 -- 因此,我们使用以下方式:将dblink名称原样放入,但需要转义单引号 ' "' || REPLACE(dblink_name, '"', '""') || '" ''; END;', enabled => TRUE, auto_drop => TRUE ); END; / ``` 解释: - 作业名:我们使用目标用户(schema_name)作为作业的所有者,作业名我们加了一个时间戳以确保唯一。 - job_action:我们构建了一个动态SQL,使用EXECUTE IMMEDIATE执行删除语句。在删除语句中,dblink名称用双引号括起来,并且如果dblink名称本身包含双引号,则用两个双引号表示(通过REPLACE函数将双引号替换成两个双引号)。 - 设置enabled为TRUE,作业创建后立即运行。 - auto_drop为TRUE,作业完成后自动删除。 但是,如果dblink名称中不包含小写或特殊字符,通常可以不加双引号。但为了通用性,我们加上双引号。 另外,如果dblink名称是大小写混合的,那么创建时用了双引号,删除时也必须用双引号。 注意:如果dblink名称中包含单引号,则上面的字符串拼接会出现问题。因此,我们需要处理单引号:在拼接字符串时,将dblink_name中的单引号替换成两个单引号(在SQL字符串中,两个单引号表示一个单引号)。 所以,改进后的job_action: job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "' || REPLACE(REPLACE(dblink_name, '"', '""'), '''', '''''') || '"''; END;' 解释:先替换双引号(将"替换成""),再替换单引号(将'替换成'',但在字符串中,两个单引号表示一个单引号,所以这里在动态SQL的字符串中,我们需要两个单引号来表示一个单引号,而在构建这个字符串时,我们需要用四个单引号表示两个单引号?有点绕) 实际上,在job_action这个字符串中,我们写的是: 'BEGIN EXECUTE IMMEDIATE ''...''; END;' 其中,内部的SQL字符串(即动态SQL)是用两个单引号括起来的,而内部的字符串中如果出现单引号,则需要用两个单引号表示。 因此,对于dblink_name中的单引号,我们需要在动态SQL的字符串中表示为两个单引号。所以,在构建job_action字符串时,我们需要将dblink_name中的每个单引号替换成两个单引号(即四个单引号?不对,因为外部还有一层字符串)。 具体来说,假设dblink_name为:a'b,那么动态SQL应该是: DROP DATABASE LINK "a'b" 但作为字符串,在PL/SQL块中写为: 'DROP DATABASE LINK "a''b"' 所以,在job_action中,我们需要: 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "a''b"''; END;' 因此,在构建job_action时,我们需要将dblink_name中的单引号替换成两个单引号(即:将 ' 替换成 ''),然后放在双引号中。 所以,我们可以这样构建: job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "' || REPLACE(REPLACE(dblink_name, '''', ''''''), '"', '""') || '"''; END;' 注意:先替换单引号,再替换双引号。因为替换双引号时可能会引入单引号?不会,双引号替换成两个双引号,不涉及单引号。 因此,完整的PL/SQL块如下(以变量schema_name和dblink_name为例): ``` DECLARE schema_name VARCHAR2(30) := 'SCOTT'; -- 替换为目标用户名 dblink_name VARCHAR2(128) := 'my_link'; -- 替换为dblink名称 job_name VARCHAR2(128) := '"' || schema_name || '"."JOB_DROP_DBLINK_' || TO_CHAR(SYSTIMESTAMP, 'YYYYMMDDHH24MISSFF') || '"'; job_action VARCHAR2(1000); BEGIN -- 构建job_action,注意转义 job_action := 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "' || REPLACE(REPLACE(dblink_name, '''', ''''''), '"', '""') || '"''; END;'; DBMS_SCHEDULER.CREATE_JOB( job_name => job_name, job_type => 'PLSQL_BLOCK', job_action => job_action, enabled => TRUE, auto_drop => TRUE ); END; / ``` 执行这个PL/SQL块后,作业会立即运行,然后自动删除。 但是,这种方法可能会因为作业调度程序的延迟而不会立即执行。为了确保立即执行,我们可以使用以下方式强制运行: ``` BEGIN DBMS_SCHEDULER.RUN_JOB(job_name, TRUE); -- 第二个参数TRUE表示同步执行,即等待完成 END; / ``` 但是,由于我们创建作业时已经启用了,而且作业是立即启用的,所以通常很快就会执行。如果系统繁忙,可能会有延迟。所以我们可以增加RUN_JOB的步骤,并等待它完成。 因此,修改后的PL/SQL块(包含同步执行): ``` DECLARE schema_name VARCHAR2(30) := 'SCOTT'; -- 替换为目标用户名 dblink_name VARCHAR2(128) := 'my_link'; -- 替换为dblink名称 job_name VARCHAR2(128) := '"' || schema_name || '"."JOB_DROP_DBLINK_' || TO_CHAR(SYSTIMESTAMP, 'YYYYMMDDHH24MISSFF') || '"'; job_action VARCHAR2(1000); BEGIN job_action := 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "' || REPLACE(REPLACE(dblink_name, '''', ''''''), '"', '""') || '"''; END;'; DBMS_SCHEDULER.CREATE_JOB( job_name => job_name, job_type => 'PLSQL_BLOCK', job_action => job_action, enabled => FALSE, -- 先不启用,等我们手动运行 auto_drop => TRUE ); -- 立即运行作业(同步方式) DBMS_SCHEDULER.RUN_JOB(job_name, TRUE); END; / ``` 这样,我们创建作业后立即同步执行,执行完成后作业会自动删除。 注意:如果删除dblink时出现错误(比如dblink不存在),作业会失败,但作业也会自动删除(因为auto_drop为TRUE)。我们可以查看作业日志来排查,但这里我们为了简化,没有捕获错误。用户需要确保dblink存在且名称正确。 另外,如果目标用户没有执行PL/SQL块的权限,可能会失败。但通常,删除自己的dblink的权限是有的。 总结:作为SYS用户,我们可以通过创建一个以目标用户身份运行的作业来删除该用户下的私有dblink。 但是,请注意,在生产环境中执行前,务必进行测试。 另外,引用[2]中的存储过程方法(使用DBMS_SYS_SQL)虽然有效,但由于是内部包,不推荐使用,这里就不详细说明了。 因此,我们推荐使用DBMS_SCHEDULER的方法。 注意:以上代码需要在Oracle 10g及以上版本运行,因为DBMS_SCHEDULER在10g引入。 如果用户的环境是较老的版本(如9i),则可能需要使用DBMS_JOB(但DBMS_JOB不能指定作业的所有者,所以可能不行)或者使用其他方法。 在Oracle 9i中,可能只能使用引用[2]的内部包方法,或者让目标用户自己删除(如果知道目标用户密码,可以用目标用户登录删除)。 但问题要求以SYS用户删除其他用户的私有dblink,所以如果目标用户无法配合,则可能需要使用内部包(不推荐)或者使用其他非常规手段。 因此,我们主要提供10g及以上版本的解决方案。 最后,我们生成相关问题。</think>### Sys用户删除其他用户的私有DBLink(Oracle) 在Oracle数据库中,私有数据库链接(DBLink)由创建它的用户独占管理。作为SYS用户,您可以通过以下方法删除其他用户的私有DBLink: #### ✅ 推荐方法:使用`DBMS_SCHEDULER`创建作业 ```sql BEGIN DBMS_SCHEDULER.CREATE_JOB( job_name => '"目标用户"."JOB_DELETE_DBLINK"', -- 格式:"用户名.作业名" job_type => 'PLSQL_BLOCK', job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "DBLink名称"''; END;', enabled => TRUE, auto_drop => TRUE ); END; / ``` **参数说明**: - `目标用户`:DBLink所有者的用户名(如`SCOTT`) - `DBLink名称`:要删除的DBLink名称(如`MY_LINK`) - `auto_drop => TRUE`:作业执行后自动删除自身 **执行原理**: 通过创建以目标用户身份运行的作业,在目标用户的安全上下文中执行删除操作,绕过权限限制[^3]。 #### ⚠️ 替代方法:使用`DBMS_SYS_SQL`内部包(不推荐) ```sql CREATE OR REPLACE PROCEDURE sys.drop_other_dblink( p_owner VARCHAR2, p_dblink VARCHAR2 ) IS v_uid NUMBER; v_cur NUMBER; BEGIN SELECT user_id INTO v_uid FROM dba_users WHERE username = p_owner; v_cur := DBMS_SYS_SQL.OPEN_CURSOR; DBMS_SYS_SQL.PARSE_AS_USER( c => v_cur, statement => 'DROP DATABASE LINK "' || p_dblink || '"', userid => v_uid ); DBMS_SYS_SQL.CLOSE_CURSOR(v_cur); END; / -- 调用示例 EXEC drop_other_dblink('SCOTT', 'MY_LINK'); ``` **注意**: 此方法直接操作内部包`DBMS_SYS_SQL`,可能导致系统不稳定且不受Oracle官方支持[^2]。 --- ### 关键注意事项 1. **名称大小写处理** 若DBLink名称包含小写字母或特殊字符,必须使用双引号包裹: ```sql job_action => 'BEGIN EXECUTE IMMEDIATE ''DROP DATABASE LINK "My_Link"''; END;' ``` 2. **权限要求** SYS用户需要具备: - `CREATE ANY JOB`权限 - `MANAGE SCHEDULER`系统权限 3. **验证结果** 删除后检查: ```sql SELECT * FROM DBA_DB_LINKS WHERE OWNER = '目标用户'; ``` 4. **错误处理** 常见错误: - ORA-02024:DBLink未找到 → 检查名称拼写 - ORA-01031:权限不足 → 检查SYS用户权限 - ORA-12012:作业执行错误 → 检查DBLink依赖对象 > ⚠️ **重要提示**:删除前请确认无活动会话使用该DBLink,避免影响业务系统[^1]。 --- ### 操作流程 1. 以SYS身份登录SQL*Plus 2. 确认目标DBLink存在: ```sql SELECT owner, db_link FROM dba_db_links WHERE owner = '目标用户'; ``` 3. 执行推荐方法中的PL/SQL块 4. 验证删除结果 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值