保证执行Java的安全(转)

保证执行Java的安全

作者:Kuassi Mensah

DBA关于OracleJVM安全机制的观点

安全性是DBA们、首席技术官们、每一个设计和开发人员以及一个系统的每个最终用户主要关心的问题,这样的系统运行着与最具价值的企业资产--业务数据关系密切的软件模块。与传统的基于JDK的Java虚拟机完全不相同,Oracle Java虚拟机(Oracle Java Virtual Machine,OracleJVM)使你能够在Oracle9i数据库内运行Java对象,因而给你提供Oracle数据库的全部性能优势。但是,OracleJVM如何加强Java的安全性呢?

这要归功于运行在Oracle9i数据库中的Java代码能够从安全性丰富的环境中受益,在这个环境中你可以以多种方式进行精细调优。你可以利用数据库的安全机制,如用户认证安全性、数据库模式安全性、登录用户安全性和有效用户安全性。OracleJVM还提供了附加的特性,如类解析(class-resolution)安全性和Java 2安全性。我们将在下面讨论这些机制中的每一个机制,但我们首先快速了解一下OracleJVM本身。

OracleJVM

从Oracle8i第8.1.5版开始提供的OracleJVM执行环境允许Java对象(Java 2 标准版--J2SE)在RDBMS内核中运行。OracleJVM与Oracle的数据库-会话体系结构紧密集成。这一体系结构协调了与J2SE完全兼容的传统JDK VM和自身带有内存模型的Oracle数据库、错误处理以及可伸缩性之间的差异。

当在数据库会话中的第一次调用Java代码时,该会话在数据库服务器进程中透明地激活一个实际上专用的JVM。对Java的后续调用将从已能执行Java的进程得到好处。所有会话共享来自JVM系统类(java.*、oracle.aurora.*、 oracle.jdbc.*)以及任何以前加载到数据库中的其他类的只读数据。 这意味着每个用户只占用一小块内存,因而你可以不断添加Java客户机而仍能维护线性可伸缩性。在默认情况下,轻型的、服务器端的JDBC驱动程序在每个已能执行Java的会话中被激活。JDBC驱动程序提供基于函数的SQL数据访问。

OracleJVM提供与J2SE的兼容性。在Oracle9i第2版中,OracleJVM还与J2SE 1.3.1兼容。OracleJVM对J2SE的支持意味着通过使用Java库,Oracle9i数据库的功能得到了扩展。例如,你可以在OracleJVM中使用Java安全套接字扩展(Java Secure Socket Extension,JSSE),来把Java HTTPS标注(callouts)放到外部系统中。

由于该数据库支持Java,所以你可以在整个中间层和数据库层划分JDBC、SQLJ和JMS应用程序。你还可以划分高级数据绑定J2SE应用程序,后者能够连接SQL、XML、Java 2平台企业版(Java 2 Platform Enterprise Edition,J2EE)和Web服务。(欲了解更多详细内容,请见 "下一步"中的内容。)

用户认证安全性

一个Oracle9i数据库用户,典型的就是一个客户端应用程序或一个JDBC 连接,它需要经过确定身份、认证和授权之后才能创建会话。Oracle Net和(一定程度上)第2类JDBC驱动程序(也称为OCI driver驱动程序)支持几种用户认证机制。这些方法包括传统的密码认证、强力认证机制(如Kerberos、CyberSafe、RADIUS、令牌卡、智能卡、Biometrics、PKI和基于证书的认证)、代理认证和授权以及Oracle单一登录(Single Sign-On,SSO)。数据库客户端一旦通过认证,就会有一个新的数据库会话与这个调用者(requester)相关联。(欲了解有关用户认证的更多详细内容,请阅读Oracle9i第2版安全性概述白皮书--见"下一步"。)

数据库模式安全性

传统的基于JDK的Java虚拟机允许你执行直接从Web上下载的Java类。对于OracleJVM,一个Java类驻留在数据库中,因此它受到保护其他数据库对象的安全性特性的控制。具体地说,在数据库模式内可以组织、存储、搜索和执行Java类、源和资源。你需要把Java类加载到一个特定的数据库模式中并对它进行确认之后,才能用OracleJVM执行它。要加载Java类,你可以使用loadjava命令行实用程序或IDE(如Oracle9i JDeveloper)。你必须有CREATE PROCEDURE特权才能向自己的模式中加载类,要有CREATE ANY PROCEDURE特权才能向其他用户拥有的模式加载类。这些保护措施提供了一个可靠的Java执行环境,它比基于JDK的JVM更不容易受到恶意代码的攻击。

但是,任何Java类都需要共享J2SE和系统类。这些类在PUBLIC模式或SYSTEM模式中只加载一次。按照定义,可以在任何其他模式中访问PUBLIC模式中的对象。如果Java系统类被加载到SYSTEM模式中,则可以通过PUBLIC同义词访问它们,同义词就是提供对普通对象或资源的公用可视性的一种数据库机制。

OracleJVM不允许用户替换系统类或向系统包中加载新的类。如果用户希望向另一个模式加载这样的类,则他必须得到JserverPermission(LoadClassInPackage. )许可。下面的命令授予用户向oracle.aurora.*包中加载类的SCOTT许可:

 

dbms_java.grant_permission('SCOTT', 'SYS:oracle.aurora.tools.*', null);

 

Java类由在其中它们被加载的模式--称为定义模式(defining schema)所拥有。你可以通过将Java类组织到独立的模式中来为它们提供不同的安全级别。例如,假设你在不同的模式中定义了类A和类B。为了让类A引用类B,类A的定义模式必须被授予执行类B的权利。为了实现这一点,你可以使用loadjava实用程序中的授权选项。通过为特定类创建新的模式以及控制对这些类的执行权限,你可以为Java应用程序设计细粒度的安全性。

在下面的例子中,Betty和Bob得到授权在模式TEST中执行类alpha:

 

loadjava -thin -schema test 衭 SCOTT/TIGER@localhost:5521:orcl 
     -grant BETTY,BOB alpha.class

类解析安全性

OracleJVM使用解析器规范(resolver spec)在数据库模式中搜索和定位Java类。一个解析器规范通常包含多个模式。它在概念上与JDK环境中的类路径类似。与JDK相比,解析器规范是按类来定义的。这里不存在通用类路径。相反,每个模式都有一个默认的解析器规范。

下面的例子说明了定义解析器规范范围的几种不同方法:

 

  • 默认的解析器规范包括定义模式SCOTT和PUBLIC模式,它还把调用者连接到通过PUBLIC同义词列出的所有类:

     

     

    Default resolver spec = 
    
      '{(* SCOTT) (* PUBLIC)}'
    

     

     

  • 调用者通过使用默认的解析器规范加载Java类,默认的解析器规范在定义程序(definer)的模式和PUBLIC模式内进行搜索:

     

     

    loadjava 衦esolve ...
    

     

     

  • 调用者通过使用包括SCOTT、OTHER和PUBLIC模式的解析器规范加载Java类:

     

     

    loadjava -resolve -resolver 
      "((* SCOTT)(* OTHER)(* PUBLIC))" ...
    

 

在解析器规范解析对一个类的引用之前,该类必须是可见的,而且调用者必须有执行它的许可。此外,OracleJVM要求对其他类的所有引用都必须在部署期间(加载期间)被解析,除非它被告知推迟到运行时解析。在一个类可以被使用之前,所有引用都必须被解析。例如,下面的解析器规范导致忽略在SCOTT或PUBLIC模式中没有找到的所有类:

 

loadjava -resolve -resolver "((* SCOTT) 
  (* PUBLIC))" -genmissing 

 

genmissinggenmissing是loadjava的一个可选项,它允许你处理不存在的类。它命令loadjava创建和加载被引用但未被定义的类的占位符定义。通过解析对缺失类的引用,genmissing选项允许运行Java代码,但由于缺失类有占位符定义,所以不能调用它们的方法。类解析体系结构提供了对类的可视性和安全性的灵活而又细粒度的控制。

登录用户和有效用户的安全性

当用户登录到数据库时,会通过登录用户的身份或模式身份创建一个会话。所有数据库操作,包括SQL语句、PL/SQL包和Java存储过程的PL/SQL外壳(wrapper),都以登录用户的身份被执行。如果登录用户的模式已经被授予执行其他类的许可,那么一个会话就可以执行在其他模式中定义的Java类。

但是,你可以动态地替换Java类运行的有效身份。默认情况下,有效的身份就是登陆用户的身份。通过使用类似于UNIX setuid工具的该数据库的有效用户机制,你可以在Java类级别或PL/SQL存储程序级别上改变身份。

你可以通过分配一个类的调用者的权限和定义者权限来设置有效身份。

 

  • 调用者的权限。 在默认情况下,一个Java类与调用者的权限相关联;该类并不绑定到它的定义模式。执行该类的任何会话的当前用户与该会话的登陆用户是同一个。在运行时要核对权限,而外部引用则在当前用户的模式中进行解析。利用调用者的权限,你可以在多个模式和应用程序间集中并共享代码,同时保持数据私有并单独地存储在每个模式中。

     

     

  • 定义者的权限。 通过分配一个类的定义者权利,你可以把类绑定到其定义模式上。执行该类的任何会话的有效用户,其身份被临时改变为该类的定义模式的身份,而且在定义模式中寻找所有不合格的引用。执行使用定义者权限加载的Java类时不要求将进行调用的会话像拥有该代码的模式那样被连接。

你可以在PL/SQL外壳上指定有效用户权限(通过使用Call规范,后者向SQL环境提供公用的静态Java方法),也可以使用loadjava实用程序在Java类自身上指定有效用户的权限。这些权限只有在Java类或PL/SQL包通过服务器端JDBC被调用时才有效。

在下面的例子中,有效用户的权限分别在PL/SQL外壳和Java类上被定义。

 

  • 通过PL/SQL界面指定调用者的权限(当前用户):

     

     

    CREATE [OR REPLACE] PROCEDURE [schema_name.]procedure_name
    [(parameter_list)]
    [AUTHID CURRENT_USER] AS ...
    

     

     

  • 用loadjava在Java类上指定调用者的权限(当前用户):

     

     

     
    loadjava {-user | -u} <user>/<password>[@<database>] [options]
    <file>.java | <file>.class | <file>.jar |
     <file>.zip |<file>.sqlj | <resourcefile> ...
    [-nodefiner]
    

     

     

  • 通过PL/SQL界面指定定义者的权限:

     

     

    CREATE [OR REPLACE] PROCEDURE [schema_name.]procedure_name
    [(parameter_list)]
    AUTHID DEFINER ...
    

     

     

  • 用loadjava在Java类上指定定义者的权限:

     

     

    loadjava {-user | -u} <user>/<password>
    [@<database>] [options]
    <file>.java | <file>.class | <file>.jar |
     <file>.zip |<file>.sqlj | <resourcefile> ...
    -definer 
    

有关有效用户权限的更多详细内容,请阅读《PL/SQL用户指南和参考》(PL/SQL User's Guide and Reference)第8章(见"下一步")。

Java 2安全性

下一步

阅读
更多有关Java 存储过程的内容
otn.oracle.com/tech/java/jsp/index.html
otn.oracle.com/oramag/oracle/03-jan/o13java.html

更多有关OracleJVM安全性的内容
《PL/SQL用户指南和参考》(PL/SQL User's Guide and Reference)
《Oracle9i Java开发人员指南》(Oracle9i Java Developer's Guide)
otn.oracle.com/documentation/oracle9i.html

更多有关用户认证的内容
otn.oracle.com/deploy/security/oracle9iR2

有关数据库Web服务的内容
otn.oracle.com/tech/webservices

了解
有关数据库中Java的更多知识
otn.oracle.com/tech/java/java_db

有关数据库中安全性的更多知识
education.oracle.com keyword search: security

有关Sun的Java 2 Platform安全体系规范的更多知识
java.sun.com/security

 

Java 2安全性的目标就是提供细粒度的访问控制、易于配置的安全策略、易于扩展的访问控制结构以及安全性扩展。

OracleJVM完全符合Java 2安全性规范要求,但它的实现过程与JDK VM存在以下几点不同:

 

  • 与JDK不同,OracleJVM的安全性是基于定义模式的。也就是说,许可是授予定义模式的,而不是授予Java代码库。

     

     

  • 每个Java 2许可都由存储在PolicyTable中的许可对象来表示的,而且由行关键字来标识。在一个安全的、带有访问限制的模式中定义PolicyTable。(相反,JDK在一个策略文件(policy file)中保存各种许可。)你必须在PolicyTable中指定所有的安全策略,PolicyTable可以通过DBMS_JAVA包或PolicyTableManager方法来扩展和更新,如下例所示:

     

     

    Call dbms_java.grant_permission(grantee,
      permission_type, permission_name, 
      permission_action)
    
    oracle.aurora.rdbms.security
      .PolicyTableManager.grant(grantee, 
      permission_type, permission_name, 
      permission_action)
    

     

     

  • 与JDK不同,OracleJVM支持授予和撤销或限制许可。只有JAVA_ADMIN用户才能向其他用户授予访问和更新 PolicyTable的许可。

     

     

  • OracleJVM支持所有Java 2许可以及Oracle定义的许可。另外,具有适当权限的最终用户可以定义和存储他们自己的许可。

     

     

  • SecurityManager总是在能执行Java的会话中被初始化和激活。

 

OracleJVM安全性的最佳实践

Oracle推荐你采取以下措施来维护你Java应用程序的安全性:

 

  • 显式地授予每一个许可。采用细粒度的方法使你能够符合Java 2安全性的要求。JAVASYSPRIV和JAVAUSERPRIV角色只是为向后兼容而保留的许可组。

     

     

  • 只将java.io.FilePermission授予显式列出的文件。

     

     

  • 一般而言,在授予与Classloader和java.lang有关的许可时保守一些为好。例如,授予RuntimePermission(createClassLoader)许可与授予所有许可的效果相同。遵循这些建议将有助于确保你的Java应用程序的安全性。
Kuassi Mensah (kuassi.mensah@oracle.com) 是Oracle公司服务器技术部的集团产品经理。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值