程序权限被拒绝

Permission denied to procedure

我已经按照 this post 并在数据库中创建了一个过程。然后我在我要查看PDF的页面中创建了一个新区域。在源代码中我把这个:

<embed src="#OWNER#.download_my_file?p_file=21" width="500" height="375">

21 是我在程序中指定的 table 中的 ID 之一。这只是暂时的固定值。

当我查看页面时,出现错误:

(Access to the procedure named: INGTOCBADB.download_my_file is denied)

我该如何解决这个问题?

您需要将您的过程添加到 APEX_xxxxxx 架构中函数 WWV_FLOW_EPG_INCLUDE_MOD_LOCAL 允许的过程调用的 "whitelist" 中:

create or replace Function wwv_flow_epg_include_mod_local(procedure_name IN VARCHAR2)
return boolean
is
BEGIN
   IF upper(procedure_name) IN (
   'DOWNLOAD_MY_FILE',
   ... other procedures already listed
   )
   THEN
      return TRUE;
   ELSE
      return FALSE;
   END IF;
end wwv_flow_epg_include_mod_local;

另一种方法是使用应用程序进程。与允许 public 访问数据库过程相比,我更喜欢这种方式。

您可以在博客 link 中找到操作方法,并在下面复制了部分内容。该博客由 Oracle 软件开发总监兼 Apex 经理 Joel Kallman 撰写。这家伙值得一听

http://joelkallman.blogspot.be/2014/03/yet-another-post-how-to-link-to.html

我复制了博客的大部分内容并将 links 更新为工作文档 links。


Firstly, a way not to do this is via a PL/SQL procedure that is called directly from a URL. I see this "solution" commonly documented on the Internet, and in general, it should not be followed. The default configuration of Oracle Application Express has a white list of entry points, callable from a URL. For security reasons, you absolutely want to leave this restriction in place and not relax it. This is specified as the PlsqlRequestValidationFunction for mod_plsql and security.disableDefaultExclusionList for Oracle REST Data Services (nee APEX Listener). With this default security measure in place, you will not be able to invoke a procedure in your schema from a URL. Good!

The easiest way to return an image from a URL in an APEX application is either via a RESTful Service or via an On-Demand process. This blog post will cover the On-Demand process. It's definitely easier to implement via a RESTful Service, and if you can do it via a RESTful call, that will always be much faster - Kris has a great example how to do this. However, one benefit of doing this via an On Demand process is that it will also be constrained by any conditions or authorization schemes that are in place for your APEX application (that is, if your application requires authentication and authorization, someone won't be able to access the URL unless they are likewise authenticated to your APEX application and fully authorized).

  1. 导航到应用程序生成器 -> 共享组件 -> 应用程序项
  2. 点击创建
    • 姓名:FILE_ID
    • 范围:应用
    • Session 国家保护:无限制
  3. 导航到应用程序生成器 -> 共享组件 -> 应用程序进程
  4. 点击创建
    • 姓名:GETIMAGE
    • 要点:按需:运行此应用程序在页面进程请求时处理。
  5. 点击下一步
  6. 对于处理文本,输入以下代码:

    begin
      for c1 in (select *
                 from my_image_table
                where id = :FILE_ID) loop
        --
        sys.htp.init;
        sys.owa_util.mime_header( c1.mime_type, FALSE );
        sys.htp.p('Content-length: ' || sys.dbms_lob.getlength( c1.blob_content));
        sys.htp.p('Content-Disposition: attachment; filename="' || c1.filename || '"' );
        sys.htp.p('Cache-Control: max-age=3600');  -- tell the browser to cache for one hour, adjust as necessary
        sys.owa_util.http_header_close;
        sys.wpg_docload.download_file( c1.blob_content );
    
        apex_application.stop_apex_engine;
      end loop;
    end;
    

然后,您需要做的就是在您的应用程序中构造一个URL来调用此应用程序进程,如Application Express Application Builder Users' Guide. You could manually construct a URL using APEX_UTIL.PREPARE_URL中所述,或者在声明中指定一个link报告列的属性。请务必指定 APPLICATION_PROCESS=GETIMAGE 的请求(或任何您的应用程序进程名称)。 URL 看起来像:

f?p=&APP_ID.:0:&APP_SESSION.:APPLICATION_PROCESS=GETIMAGE:::FILE_ID:<some_valid_id>

仅此而已。

一些结束语:

  1. 注意为申请流程指定的授权方案。默认情况下,授权方案将为 "Must Not Be Public User",对于需要身份验证的应用程序,通常为 acceptable。但也请记住,您也可以根据其他授权方案限制这些 link。
  2. 如果您想内联显示图像而不是通过浏览器下载,只需将 Content-Disposition 从 'attachment' 更改为 'inline'。
  3. 此代码的合理扩展和优化是向基础 table 添加版本号,每次文件更改时递增它,然后在 URL.这样做,结合 MIME header 中的 Cache-Control 指令,可以让客户端浏览器缓存它很长时间,而不会再次 运行 您的按需处理(因此,节省您的宝贵的数据库周期)。
  4. 应用程序也可以在 page-level 上定义,因此如果您希望下载 link 受特定页面上授权方案的限制,您也可以这样做。
  5. 请注意它的使用方式。如果您不实施某种形式的浏览器缓存,那么一份在页面上内联显示 500 张图像的报告将导致每个用户每次页面视图向 APEX 引擎和数据库发出 500 次请求!哎哟!然后,DBA 开始寻找攻击他们数据库的人并报告 "APEX is killing our database" 只是时间问题。有一个excellent explanation of cache headers here.

再次感谢 Joel Kallman。

对我有用的是将条目添加到 default.xml 文件,这样 ORDS 就知道什么是白名单

EG

<entry key="security.inclusionList">wwv_flow*,f,n,p,q,cust,apex,ADMIN.*</entry>