如何隐藏我的 Oracle 表?
以下是场景(简化示例):
我有一个名为 ABC 的 Oracle 用户/模式。 ABC 拥有一个名为 TRN 的表。客户端代码作为 ABC 连接到数据库并从 ABC.TRN 中进行选择。
到目前为止,一切都很好。但是,我不希望客户端代码指定 Oracle 模式名称。现在我想我已经删除了客户端代码中引用架构的所有引用,但我想对此进行测试以确保。
所以我想创建一个名为 DEF 的新用户/模式,客户端将使用它来连接到数据库。当客户端应用程序从 ABC.TRN 中选择时,它必须给出错误。但是,如果客户端应用程序从 TRN(无模式名称)中进行选择,则它必须返回数据。
有什么方法可以做到这一点吗?请注意,DEF 必须与 ABC 位于同一数据库上,只有一个表 TRN 表(由 ABC 拥有),并且我无法使用数据库链接。
我尝试创建一个新的 XYZ 用户,其同义词指向 ABC.TRN,并赋予其对 ABC.TRN 的选择权限。然后我创建了 DEF 用户,其同义词指向 XYZ.TRN,并赋予 DEF 对 XYZ.TRN 的选择权限。这可行,但 Oracle 足够聪明,知道如果 DEF 有权从 XYZ.TRN 中选择,那么它也有权从 ABC.TRN 中选择,从而违背了本次练习的目的,因为我希望这种情况给出错误。
交给你了...
Here's the scenario (simplified example):
I have an Oracle user/schema called ABC. ABC owns a table called TRN. Client side code connects to the database as ABC and selects from ABC.TRN.
So far so good. However, I don't want the client code to specify the Oracle schema name. Now I think I have removed all references in the client code that refer to schema but I want to test this to make sure.
So I want to create a new user/schema called DEF which will be used by the client to connect to the database. When the client application select from ABC.TRN, it must give an error. However if the client application selects from TRN (no schema name), it must return the data.
Is there some way to do this? Note that DEF must be on the same database as ABC, there is only one table TRN table (owned by ABC) and I cannot use database links.
I have tried creating a new XYZ user with a synonym pointing to ABC.TRN and giving it select rights on ABC.TRN. Then I created the DEF user with a synonym pointing to XYZ.TRN and gave DEF has select rights on XYZ.TRN. This works but Oracle is clever enough to know that if DEF has rights to select from XYZ.TRN then it also has rights to select from ABC.TRN, thereby defeating the purpose of this exercise as I want this case to give an error.
Over to you...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
没有简单的方法可以做到这一点。
一种方法是政治性的:进行代码审查,也许通过自动搜索代码库,当人们这样做时就拍拍手腕。
架构方法类似于您的三个模式结构,但有一个微妙的变化:中间的模式使用视图。因此,模式 ABC 拥有表并将其权限授予模式 XYZ。模式 XYZ 针对这些表构建简单视图(SELECT *,无 WHERE 子句)并向模式 DEF 授予视图权限。架构 DEF 只能从 XYZ 对象中进行选择。
当然,所有这些努力仍然无法阻止开发者编写
SELECT * FROM xyz.whatever
。在这种情况下,我请您参考我的第一个建议 8-)实际上,有一种非常非常邪恶的方法可以做到这一点。在面向应用的架构 (DEF) 中使用同义词,然后更改数据拥有架构 (ABC) 的名称。
当然,只有当您的安装脚本完全参数化且没有自己的硬编码模式名称时,您才应该尝试此策略。
There is no easy way to do this.
One approach would be political: institute code reviews, perhaps with automated searches of the code base, and just slap wrists when people do this.
The architectural approach would be similar to your three schema structure, but with a subtle twist: the schema in the middle uses views. So, schema ABC owns tables and grants permissions on them to schema XYZ. Schema XYZ builds simple views against those tables (SELECT *, no WHERE clauses) and grants permissions on the views to schema DEF. Schema DEF can only select from XYZ objects.
Of course, all that effort still won't prevent develoeprs from coding
SELECT * FROM xyz.whatever
. In which case I refer you to my first suggestion 8-)Actually there is one, really really evil way to do this. Use synonyms in the app facing schema (DEF)and then change the name of the data owning schema (ABC).
Of course, you should only attempt this stratagem if your install scripts are fully paramterized, with no hard-coded schema names of their own.
你真的需要抛出一个错误吗?或者您只需要验证应用程序是否未使用完全限定名称(即
ABC.TRN
)?假设您只是想验证应用程序是否未使用完全限定名称,并且抛出错误只是您想到的通知您的机制,您可以通过查询
V$SQL
V$SQL 来验证代码code> 在应用程序运行时。V$SQL
列出Oracle中共享池中的所有SQL语句。如果您在应用程序运行时定期查询该表,您将看到它发出的所有 SQL 语句。然后,您可以记录使用完全限定名称的任何语句。例如,
如果您在应用程序运行时每隔几分钟运行一次该过程,您将看到任何使用完全限定名称的 SQL,并将该语句记录在
LOG_OF_BAD_SQL
表中。对于一个编写良好的系统来说,每隔几分钟可能就有点过分了,您只需要确保它的运行频率比共享池中的语句老化的频率更高。如果您的应用程序没有正确使用绑定变量,则可能需要每隔几分钟进行一次,以避免丢失任何内容。Do you really need to throw an error? Or do you simply need to verify that the application is not using fully qualified names (i.e.
ABC.TRN
)?Assuming that you're merely interested in verifying that the application is not using fully qualified names and that throwing the error was merely the mechanism you thought of to notify you, you can probably verify the code by querying
V$SQL
while the application is running.V$SQL
lists all the SQL statements in the shared pool in Oracle. If you query that table regularly while your application is running, you'll see all the SQL statements it issues. You can then log any statements that use fully qualified names.For example
If you run that procedure every few minutes while your application is running, you'll see any SQL that is using the fully qualified name and log that statement in the
LOG_OF_BAD_SQL
table. Every few minutes is probably overkill for a well-written system, you just need to ensure that it is run more frequently than statements are aged out of the shared pool. If you have an application that doesn't use bind variables appropriately, that may need to be every few minutes in order to avoid missing anything.改变会话怎么样?
这将允许您以用户身份登录,该用户已被授予对模式 X 拥有的表的选择权限,并执行将会话更改为模式 X 的 SP。前端代码不会知道发生了这种情况。
但是,如果您的前端代码指定模式 X:
我认为它不会引发错误。
也许您可以解释为什么客户端代码在使用正确的当前架构名称时收到错误很重要?
是否可以创建一个新模式,转移旧模式对象的所有权,然后删除旧模式,然后使用上面的方法?
PS 请参阅登录后触发器:http://psoug.org/reference/system_trigger.html
PPS 自您已详细说明您的要求:
例如,如果对象的位置不在 CURRENT_SCHEMA 中,而是在其他某个架构中,这两个架构恰好都有名为 CUSTOMER 的表,则数据库引擎将不知道客户端应用程序发送给它的语句应该引用如果表名不是这样限定的,则使用其他模式。这意味着引擎不具备一定程度的元知识,尽管它为开发人员提供了以存储过程和触发器的形式创建此类智能的工具,并授予/撤销对对象的控制。
成功地将这种智能放入后端的最佳机会是撤销对表和视图的所有直接权限,并要求客户端应用程序通过存储过程访问对象,因为数据库引擎本身不知道应用程序发布之类的事情水平。我认为没有纯粹的声明性方法可以实现它。这在很大程度上必须是程序性的。您自己的后端逻辑必须承担在不同模式中的同名对象之间进行仲裁的责任。也就是说,像 AFTER LOGON 触发器和 ALTER SCHEMA 这样的功能应该对您有帮助。
How about ALTER SESSION?
That would allow you to log in as a user, to whom select rights have been granted to a table owned by schema X, and execute an SP that changes the session to schema X. The front-end code would not know that this had happened.
However, if your front-end code specifies schema X:
I don't think it will raise an error.
Perhaps you could explain why it's important that the client-code receive an error when it uses the correct current schema name?
Is it possible to create a new schema, transfer ownershp of the old schema's objects, and then drop the old schema, and then use the approach above?
P.S. See AFTER LOGON triggers: http://psoug.org/reference/system_trigger.html
P.P.S. Since you have elaborated upon your requirements:
If the location of the object is not in the CURRENT_SCHEMA but in some other schema, both of which happen to have tables called CUSTOMER, for example, the database engine won't know that the statement sent to it by the client app should be referencing the other schema if the tablename is not so qualified. That implies a level of meta-knowledge the engine doesn't have, though it gives the developer the tools to create such intelligence in the form of stored procedures and triggers and grant/revoke control over objects.
Your best chances of success in putting this intelligence in the back end would be to revoke all direct rights to tables and views and require client apps to access objects via stored procedures, because the database engine per se doesn't know about things like application release levels. I see no purely DECLARATIVE way to accomplish it. It would have to be procedural in large part. Your own back-end logic would have to assume responsibility for arbitrating between objects of the same name in different schemas. That said, features llike AFTER LOGON triggers and ALTER SCHEMA should prove helpful to you.
你做不到。同义词只不过是指向其他模式对象的指针。您授予对实际对象的访问权限,而不是同义词。来自 Oracle 文档:
http://download.oracle。 com/docs/cd/B28359_01/server.111/b28310/views003.htm
You can't do it. Synonyms are nothing but pointers to other schemas' objects. You grant access to the actual object, not the synonym. From the Oracle docs:
http://download.oracle.com/docs/cd/B28359_01/server.111/b28310/views003.htm