`
Lewiss
  • 浏览: 20481 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JNDI Glean

    博客分类:
  • J2SE
阅读更多
JNDI 基本说明

JNDI ( Java Naming and Directory Interface ),是 Java 提供的一组与各种命名目录服务系统交互的接口。它是一套标准的接口,独立于各种命名目录服务系统,与具体类型的命名目录服务无关。Java 应用程序通过 JNDI 接口与命名目录服务交互,交互细节由服务提供者实现,Java 应用程序无需关心。
(个人觉得这是JAVA 的特点:向Java应用程序开发人员开放简单的接口,复杂的实现细节由服务提供者完成)

命令目录服务包括两个服务:命名服务(Naming Service)和目录(Directory Service)服务。命名服务就是用一个人类容易理解的名称与对象相关联,并且允许通过该名称找到与之对应的对象。我们天天都会用到的命名服务:DNS。个人觉得,目录服务是命名服务的超集,目录服务除了有命名服务的功能外,它的对象还可以有属性。常用的目录服务类型有 LDAP 等。


JNDI 上下文
JNDI 一个主要功能就是用名字(name)来标识对象(object)。name 在 JNDI 中唯一,它跟某个特定的 object 关联,这种关联关系称之为 binding。binding的集合在 JNDI 中称为上下文 context。在JNDI 特定的上下文中,通过 name就可以找到相应的对象。

Naming Service Context:命名服务上下文视图:


在上图中,a 为根 context,在它下面绑定有 dog、pig和 sheep 三个对象,同时又有 b 和 c 两个子 context,而 b 中有 d 这个子 context,d 又有 e 这个子 context,每个 context 中都绑定了相应的对象。
如果当前 context 为 a,那么 acontext.lookup(“dog”)就得到 dog 对象,而 acontext.lookup(“b/d/e/cat”) 就可得到猫这个对象。
如果当地 context 为 d,那么 dcontext.lookup(“wolf”) 就可得到 wolf 对象,dcontext.lookup(“e/rabit”) 就可得到 rabit 对象。

Directory Service Context:目录服务上下文视图:


可以看到,目录服务上下文 context 与命名服务上下文结构关系相似,只是目录服务上下文的中的对象多了属性。如在 a 上下文中,dog 对象有 name、color 和category属性,在 b 上下文中,cat 对象也有相同的属性。


也可以用map来帮助理解JNDI 的context。一个map 就相当于一个 JNDI context, map 的一个 entry 就是 JNDI context 的一个 binding,而 entry 的 key 相当于 binding 的 name,entry 的value 相当于 binding 的 object。当然这种理解不是非常准确的,因为 JNDI 的 context 还有目录层次的结构,但是可以用子 map 的方式来理解整个 JNDI 的 context,如下图所示:



在上图中,如果当前 context 为 rootMap,那么 context.lookup(“/mysqlDS”) 将得到 mysql 的连接池对象 DataSource。因为name “/mysqlDS”是跟 DataSource 绑定的;如果用context.lookup(“/jmxServerUrl”) ,将得到 JMX 服务器的连接 URL 对象 JMX_URL;同理,context.lookup(“/name_n+1/sub_name_1”) 将得到对象 sub_object1。

如果当前context为 subMap1,那么用context.lookup(“mysqlDS”) 就可以得到DataSource,而不用在 “mysqlDS” 中加上 “/”。同时,context.getSubContext(“name_n+1”) 可以得到 subMap2 的 context subcontext,并且 subcontext.lookup(“sub_name_1”) 就可得到对象 sub_object1。
在上图中,上下文结构及对象信息是维护在命名目录服务器中的, JNDI 只是操作接口。


JNDI 架构
JNDI 的实现原理其实跟 JDBC 的实现原理是一样的。在 JDBC 中,Java 定义了一套标准的、独立于数据库系统的 API。JDBC 开发者只管使用 JDBC 的 API,并加载(安装)相应数据库的驱动即可,完全不用理会该数据库驱动是怎么跟它的数据库交互的。如 JDBC 的设计架构如下图所示:


在上图中,Java 应用程序 Application1 和 Application2 只与 JDBC API 交互,而不用管数据库的 JDBC驱动是怎么跟数据库交互的(JAVA 又是这样:向Java应用程序开发人员开放 JDBC接口,复杂的实现细节由相应的 JDBC 驱动完成)。如果系统用的是 MySQL 数据库,那么就得加载 MySQL JDBC 驱动,如果是 Oracle 数据库,那么就得提供 Oracle 的 JDBC 驱动,驱动管理者(DriverManager)会自动帮Java 应用程序 Application1 和 Application2 选择对应的 JDBC 驱动与数据库进行交互。

JNDI 的实现架构跟 JDBC 的实现架构相似,如下图所示:


JNDI API 对应于 JDBC API
Naming Manager 对应于 Driver Manager
LDAP、DNS、RMI对应于 MySQL、Oracle 的 JDBC 驱动

Java Application 只与 JNDI API 交互,而不管具体的命名目录服务系统是 LDAP、DNS 还是 RMI。如果系统与 LDAP 命名目录服务系统交互,那么必须加载(安装)LDAP 驱动,如果与 DNS 命名服务系统交互,那么必须加载(安装)DNS 驱动。


JNDI SPI
在 JNDI 中,有一个概念叫做 SPI(Server Provider Interface),服务提供者接口,是 JNDI 定义的标准接口。服务提供者根据命名命令服务系统的不同,需对接口做相应的实现,并使用该实现与命名命令服务系统交互。如上图中,LDAP、DNS、RMI 就是服务提供者,它们都实现了标准的 LDAP、DNS、RMI 访问协议,使用这些协议,可以与 LDAP 系统、DNS 系统和RMI 服务器交互。
如,MySQL 和 Oracle 的 JDBC 驱动就相当于 JNDI 中的服务提供者。

Java 从 1.3 版本开始就包含了 LDAP、CORBA和 RMI 的驱动实现(服务提供者),所以访问者三种类型的命名目录服务的话不用再另外加载(安装)驱动,但如果不是,就需加载相应的驱动,就像Java 访问 MySQL 数据库需加载 MySQL 的 JDBC 驱动一样。例如通过 JNDI 访问本地文件系统的话,需加载相应的访问文件系统的驱动,sun 有一个这样的驱动实现:com.sun.jndi.fscontext.RefFSContextFactory。


Tomcat 的 JNDI SPI 实现
在上面的 JNDI 架构中,命名目录服务系统有可能部署在远程主机中,JNDI 使用相应的驱动与命名目录服务系统进行远程通信。如,LDAP 的驱动将与远程 LDAP 服务器进行通信,命名和目录信息存储于远程命名目录服务系统中。
但是在Tomcat 中稍有不同。Tomcat也有相应的 JNDI SPI 实现,但是该 SPI 实现(LDAP驱动)并不访问远程命名目录服务,它只是在内存中实现了一个虚拟命名目录服务,用于存储命名和对象信息并维护相应的绑定关系。Tomcat 中的数据源就对象就是存储于 Tomcat 实现的本地命名目录服务中的。
关于 Tomcat 的 JNDI SPI 实现,可以通过这两个类进行跟踪:
org.apache.naming.java.javaURLContextFactory
org.apache.naming.NamingContext

下面用两张图说明 LDAP 驱动与 Tomcat 驱动(SPI 实现)访问过程的不同:
LDAP 访问过程:



TOMCAT 访问过程图:



由上图可以看到,Java App 通过 JNDI 访问 LDAP 服务,LDAP 驱动要跟 LDAP服务进行远程通信,即LDAP 服务是在 Java App 的 JVM 之外的(Java App 与 LDAP 驱动在同一 JVM 内)。
但是 Tomcat 的 JNDI SPI 驱动实现不同。由上图可以看出,Servlet 通过 JNDI 接口访问 Tomcat 的虚拟命名目录服务时,Tomcat 的 JNDI SPI 实现直接访问其内存虚拟命名目录服务,而不需要跨越 JVM,即在 Tomcat 中,Servlet、Tomcat JNDI SPI 驱动以及 Tomcat 的内存虚拟命名目录都在同一 JVM 。

Tomcat 的 JNDI SPI 实现规定,命名空间必须以 java: 开头,如,我们通常在 Tomcat 中这样查找数据源(如 Servlet):
Context ctx=new InitialContext();
Object o = ctx.lookup("java:comp/env/mysqlDataSource");
DataSource ds=(DataSource)o;

这里,我们在初始化 context 的时候,不用指定加载的实现驱动,是因为 Tomcat 在启动的时候已经指定了其 SPI 实现到系统属性中:
见:org.apache.catalina.startup.Embedded
System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
                     "org.apache.naming.java.javaURLContextFactory");

当初始化 context 不指定加载驱动时,JVM 自动从指定的系统属性(javax.naming.Context.INITIAL_CONTEXT_FACTORY)中查找该驱动。
所以,我们对 mysqlDataSource 的查找请求转到 Tomcat 的 JNDI SPI 实现中,JNDI SPI 实现
根据名称从其内存的虚拟命名目录服务查找 mysql 的数据源对象,并返回给应用程序。


JNDI 简单使用
JNDI 的使用相对简单,JNDI 开发人员只需初始化一个 context 实例(可以把该实例看成是命名目录服务系统的一个镜像),并通过该 context 实例绑定对象、查找对象以及解除对象。
在初始化context 实例时,需根据目标命名目录服务系统提供相应的驱动类供 JNDI 加载使用:
Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");
Context ctx = new InitialContext(env);

在上例中,要访问的目标命名目录服务系统是本地文件系统,所以需提供 JNDI 的文件系统驱动。如果是访问 LDAP 系统,那么 context 的初始化应该提供 LDAP 驱动类:
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,   "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL,"ldap://localhost:389/o=JNDITutorial");
DirContext ctx = new InitialDirContext(env);

常用的 JNDI 操作有
查找对象:lookup(String name)
绑定对象:bind(String name, Object obj)
解除对象:unbind(String name)
还有重命名、重绑定、创建子 context 等。
关于 JNDI 的更多细节,请参阅相应书籍。
  • 大小: 14 KB
  • 大小: 17.9 KB
  • 大小: 98.1 KB
  • 大小: 4.6 KB
  • 大小: 25 KB
  • 大小: 17.4 KB
  • 大小: 7.9 KB
分享到:
评论
2 楼 snailxr 2011-04-13  
hao!!!!!!!!!!!!!1
1 楼 小哥1900 2011-03-17  
好文章,学习鸟,楼主 ,有前途~~~

相关推荐

    jndi-1_2_1.zip_jndi_jndi-1.2.1.jar

    标题中的"jndi-1_2_1.zip_jndi_jndi-1.2.1.jar"表明这是一个关于JNDI的版本1.2.1的开源软件包,其中包含了一个名为"jndi-1.2.1.jar"的JAR文件。这个JAR文件包含了JNDI库的所有实现,使得开发者可以在他们的Java项目...

    jndi-tool JNDI服务利用工具

    "jndi-tool"是一个专门针对JNDI服务的利用工具,它可以被用来测试和利用JNDI相关的安全漏洞。此工具特别关注RMI和LDAP服务,这两种服务是JNDI常用的两种协议。RMI允许Java对象在不同的Java虚拟机之间进行远程调用,...

    Tomcat中JNDI原理

    ### Tomcat中JNDI原理详解 #### 一、引言 Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的API。它为开发者提供了访问各种命名和目录服务(如DNS、LDAP等)的统一接口。在Tomcat...

    jndi所依赖的jar包

    Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的API,它为各种不同的命名和目录服务提供了统一的接口。在Java应用程序中,JNDI允许开发者查找和绑定对象,这些对象可以是数据源、...

    JNDI-Injection-Exploit-1.0-SNAPSHOT-all

    《深入解析JNDI注入攻击与防御》 Java Naming and Directory Interface (JNDI) 是Java平台中用于访问各种命名和目录服务的API,它提供了一种统一的方式来查找和访问不同类型的网络资源,如数据库、对象、服务器等。...

    JNDIDemo 以及相关文档

    Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的一组API。JNDI允许Java应用程序查找和操作各种类型的资源,如数据源、对象服务、邮件服务器等,而无需知道这些资源的具体实现细节...

    JNDI示例整合SSH

    **标题:“JNDI示例整合SSH”** 在IT领域,`JNDI`(Java Naming and Directory Interface)是Java平台提供的一种标准接口,用于访问命名和目录服务。它允许应用程序查找和操作不同类型的网络资源,如数据源、EJB等...

    用JNDI绑定DataSource

    在Java应用中,JNDI(Java Naming and Directory Interface)是一种标准的接口,它允许应用程序查找和使用资源,如数据源(DataSource),而无需直接在代码中硬编码这些资源的位置或配置信息。JNDI的核心理念是将...

    java jndi的使用

    Java JNDI(Java Naming and Directory Interface)是Java平台中用于访问命名和目录服务的一组API。它允许Java开发者在应用程序中查找和绑定资源,如数据源、EJB(Enterprise JavaBeans)、邮件服务器等。JNDI的核心...

    jndi数据库查询例子

    **JNDI(Java Naming and Directory Interface)数据库查询例子** JNDI是Java平台中用于查找和绑定资源的接口,它允许程序通过名称查找数据源、对象服务等。在Java应用中,特别是企业级Java应用中,JNDI被广泛用于...

    jndi-JNDI-Injection-Exploit

    java asm jndi_JNDI-Injection-Exploit,用于log4j2漏洞验证 可执行程序为jar包,在命令行中运行以下命令: $ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address] 其中: -C ...

    JNDI简单应用示例

    Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的一组API。它提供了一种标准的方法来查找和绑定数据,这些数据可以是对象引用、配置信息或者其他资源。JNDI通常与Java应用程序...

    JNDI.rar_JINI jndi_JNDI相关书籍_jndi

    **Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的一组API,它为各种服务提供了一种统一的接口。在Java应用程序中,JNDI允许开发者查找、绑定和管理分布式系统中的对象,如数据库...

    JNDI学习文档.doc

    **Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的一组API。它提供了一个统一的接口来查找、访问和管理分布式系统中的资源,如数据库连接池、邮件服务器、对象服务等。JNDI的核心...

    jndi连接池帮助文档

    【JNDI连接池详解】 JNDI,全称为Java Naming and Directory Interface,是一种Java API,主要用于对象的命名和目录服务。它允许开发者在无需直接与底层命名服务器交互的情况下查找和使用注册的对象,降低了编程...

    关于JNDI测试项目

    JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试项目JNDI测试...

    jboss配置MySql的JNDI

    在IT领域,特别是Java应用服务器环境下,JBoss与MySQL数据库的集成是常见需求之一,而JNDI(Java Naming and Directory Interface)在此过程中扮演着关键角色。本文将深入解析如何在JBoss中配置MySQL的JNDI数据源,...

    JNDI-Injection-Exploit-1.0-SNAPSHOT-all.zip

    Java Naming and Directory Interface (JNDI) 是Java平台中用于访问命名和目录服务的API,它允许程序查找和操作各种命名和目录服务,如 Lightweight Directory Access Protocol (LDAP)、Java Database Connectivity ...

    配置 JNDI 数据源

    在Java应用开发中,JNDI(Java Naming and Directory Interface)是一种标准接口,用于查找和管理网络资源。它允许应用程序通过一个统一的方式访问各种类型的命名和目录服务,比如数据库连接池、邮件服务器等。在...

Global site tag (gtag.js) - Google Analytics