Java存储过程中的getOutputStream抛出错误

Posted

技术标签:

【中文标题】Java存储过程中的getOutputStream抛出错误【英文标题】:getOutputStream in Java Stored procedure throws error 【发布时间】:2018-12-11 06:15:19 【问题描述】:

我正在尝试从 Java 存储过程中使用 SOAP Web 服务,并且我正在使用 getOutputStream() 命令将有效负载写入引发访问错误的连接,如下所示。

Java 调用被未捕获的 Java 异常终止:

java.security.AccessControlException:
the Permission (java.net.SocketPermission <Server-Name>:<Port> connect,resolve) 
has not been granted to INFOIFACE.
The PL/SQL to grant this is dbms_java.grant_permission 
( 'INFOIFACE', 'SYS:java.net.SocketPermission', <Server-Name>:<Port>, 'connect,resolve' ) 

但在 Oracle DB 中为架构提供了相同的访问权限,但仍然显示错误。

public class remoteConnection 
    public static String connectToFPH(String destUrl, String pacFile, String cred, String payLoad) throws Exception 

        System.out.println("Inside function");
        BrowserProxyInfo bInfo = new BrowserProxyInfo();        
        bInfo.setType(ProxyType.AUTO);
        bInfo.setAutoConfigURL(pacFile);       
        DummyAutoProxyHandler handler = new DummyAutoProxyHandler();
        try 
            handler.init(bInfo);
         catch (ProxyConfigException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        

        String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(cred.getBytes());
        URL url = new URL(destUrl);

        String proxyUrl = "";
        ProxyInfo[] ps = handler.getProxyInfo(url);     
        for(ProxyInfo p : ps)
            proxyUrl = p.toString();
        

        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.split(":")[0], Integer.valueOf(proxyUrl.split(":")[1])));

        HttpsURLConnection conn = (HttpsURLConnection)url.openConnection(proxy);
        conn.setRequestMethod("POST");
        conn.setRequestProperty ("Authorization", basicAuth);
        conn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);

        OutputStream out = conn.getOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
        writer.write(payLoad);
        writer.close();
        out.close();

        String inputLine;
        StringBuffer buf = new StringBuffer();
        if(conn.getResponseCode() == 200)
        
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            while ((inputLine = in.readLine()) != null) 
            
                buf.append(inputLine);
            
            in.close();
        
        else
        
            //throw new Exception("Unable to connect to FPH. Please contact Administrator");
            return "unable to connect";
        

        conn.disconnect();

        return buf.toString();
    


我请求这方面的帮助。 Oracle DB 中是否需要提供其他访问权限?

【问题讨论】:

【参考方案1】:

您似乎遇到了 Oracle 安全管理器。这基本上是一个由数据库表控制的经典 Java SecurityManager

“与 Java2 安全性一样,Oracle 数据库支持安全类。通常,您可以使用工具或通过编辑安全策略文件来设置代码库的权限。在 Oracle 数据库中,您可以使用 DBMS_JAVA 过程动态设置权限,它会修改数据库中的策略表。”

有关详细信息,请参阅:

"Security for Oracle Database Java Applications"

请注意,上面的示例 10-1 显示了如何使用 DBMS_Java 授予 Java 权限。 (该示例显示了FilePermission 授权。您将需要具有相关属性的SocketPermission 授权。)

【讨论】:

我们提供的权限为“dbms_java.grant_permission('INFOIFACE', 'SYS:java.net.SocketPermission', , 'connect,resolve')。有没有一些其他必要的访问权限? 1) 您是否使用了正确的服务器名称和端口? 2) 你COMMIT了吗? 是的。我使用了正确的端口和服务器。我什至可以看到 Db 表中的更新【参考方案2】:

问题可能在 ACL 列表中。 1) 检查远程主机的网络权限SELECT * FROM user_network_acl_privileges;。 2)如果没有关于它的条目。 创建新的 ACL 列表。

declare
 v_acl_name varchar2(30) := 'your_acl_name1.xml';
BEGIN
  DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(acl         => v_acl_name,
                                    description => 'Allow user to make connection',
                                    principal   => 'YOUR_USER',
                                    is_grant    => TRUE,
                                    privilege   => 'connect');

  -- optional
--  DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(acl       => v_acl_name,
--                                       principal => 'YOUR_USER',
--                                       is_grant  => true,
--                                       privilege => 'resolve');

  DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl  => v_acl_name,
                                    host => '*'); -- any host
                                    --or 
 /*DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl  => v_acl_name,
                                    host => '*.***.com');
                                    --or     
  DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl  => v_acl_name,
                                    host => 'xxx.xxx.xxx.xx-ip ');
   */                          
END;
/
COMMIT;

示例是 oracle 11 在更高版本中发生了更改。 关联: DBMS_NETWORK_ACL_ADMIN

【讨论】:

以上是关于Java存储过程中的getOutputStream抛出错误的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.IllegalStateException: getOutputStream() 已经为此响应调用

Java:如何使用response.getOutputStream()为Ajax返回结果呢?

java -- getOutputStream() has already been called for

Java Web报错:getOutputStream() has already been called for this response解决方案

如何修复“getOutputStream() 已为此响应调用”

错误渲染视图:java.lang.IllegalStateException:已为此响应调用了getOutputStream()