`
haywing
  • 浏览: 733 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

JNDI ENC与依赖注入

 
阅读更多
JNDI ENC与依赖注入
请搞清楚:通过注解还是XML注册资源,通过注入还查找得到资源,注解与XML等价方式。
以下说的是EJB引用资源

每个部署于应用服务器中的EJB容器都拥有一个属于它自己的内部注册表(internal registry),该内部注册表被称为Enterprise Naming Context(ENC),ENC是由JNDI实现的。开发人员可以通过注解或XML为某个EJB 的JNDI ENC(这是一个局部JNDI)定义资源、EJB或外部环境的别名,而后在编写EJB业务逻辑时,通过别名在JNDI中查找这些引用,在EJB3.0中,还可以把这些引用直接注入到bean数据成员中。

JNDI ENC中可以注册哪些内容
指向EJB接口的引用、JMS队列或主题的目标地址、JMS连接工厂、数据源、任何JCA资源、基本的数据类型常量,还有一些java EE服务(javax.ejb.TimerService、javax.transaction.UserTransaction、org.omg.CORBA.ORB)

如何配置JNDI ENC
ENC的JNDI名字空间可以通过XML或通过注解来定义。

如何从ENC中获取引用
通过InitialContext查找
@Stateful
@EJB(name=”ejb/ProcessPayment”,   //类级的注解
    beanInterface=ProcessPaymentLocal.class,
    beanName=”ProcessPaymentBean”)
public class TravelAgentBean implements TravelAgentRemote{
        public TicketDO bookPassage(CreditCarDO card,double amount){
            ProcessPaymentLocal payment=null;
            try{
                //EJB厂商不同,初始化方式也许不同
                javax.naming.InitialContext ctx=new InitialContext();
                //如果是本地接口,对于其他资源(如EntityManagerFactory等)也是类似的查找方法
                payment=(ProcessPaymentLocal)ctx.lookup(
                        “java:comp/env/ejb/ ProcessPayment”);//使用java:comp/env上下文
                //如果是远程接口,要用narrow方法
                Object ref= ctx.lookup(“java:comp/env/ejb/ ProcessPayment”);
                (ProcessPaymentRemote)javax.rmi.PortableRemoteObject.narrow(ref,
                     ProcessPaymentRemote.class);
            }catch(javax.naming.NamingException ne){…..}……..
        }
}

使用EJBContext查找
javax.ejb.SessionContext和javax.ejb.MessageDrivenContext接口都继承自javax.ejb.EJBContext,并且都可以用来查找ENC注册项。
@Stateful
@EJB(name=”ejb/ProcessPayment”,
    beanInterface=ProcessPaymentLocal.class,
    beanName=”ProcessPaymentBean”)
public class TravelAgentBean implements TravelAgentRemote{
        @Resource private javax.ejb.SessionContext ejbContext;
        public TicketDO bookPassage(CreditCarDO card,double amount){
            ProcessPaymentLocal payment=(ProcessPaymentLocal)ejbContext.lookup(
            “ejb/ ProcessPayment”);
            ……….
        }
}

注解注入
import com.titan.travelagent;//包名
@Stateful
public class TravelAgentBean implements TravelAgentRemote{
        @EJB private ProcessPaymentLocal payment;//通过成员变量注解直接注入
        //默认ENC名称为:com.titan.travelagent.TravelAgentBean/payment;
        //或者通过setter方法注解直接注入
        @EJB public void setProcessPayment(ProcessPaymentLocal payment){
        //默认ENC名称为:com.titan.travelagent.TravelAgentBean/processPayment;
            this.payment=payment;
        }
}

XML注入
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <ejb-local-ref>
            <ejb-ref-name> com.titan.travelagent.TravelAgentBean/payment </ejb-ref-name>注册名
            <ejb-ref-type>Session</ejb-ref-type>EJB类型有Session、Entity
            <local>com.tian.Processpayment.ProcessPaymentLocal</local>
            实现接口的EJB,由于ENC名与注解的一致,这个配置会覆盖注解
            <ejb-link>ProcessPaymentBean</ejb-link>
            <injection-target>     要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                下面的payment也可以使用processPayment,以通过setter注入
                <injection-target-name>payment</injection-target-name>
            </injection-target>
        </ejb-local-ref>
    </session>
</enterprise-beans>

XML覆盖
XML可以覆盖注解,它比注解具有一更高的优先级。覆盖方式见上一节,通过XML可以覆盖注解中要引入的实现类。

注入与继承
如果父类的数据成员或成员方法标有注入用注解,则注入父类的引用也会在子类中被引入,子类也可以覆盖父类的注入注解,但是如果父类的方法是private的,那么子类是无法覆盖它的注入注解的,这时父类和子类可能存在两个不同的引用。

不同类型的引用与注入
EJB类型的引用
@java.ejb.EJB用于引入一个EJB,@java.ejb.EJBs用于引入多个EJB
@EJB(name=”ejb/ProcessPayment”, //ENC注册名
    beanInterface=ProcessPaymentLocal.class,//接口
    beanName=”processPaymentEJB”,//实现这个接口的类,如果有多个类实现这个接口,必须指定这个
    mappedName=”….”)//根据EJB容器厂商的不同而有所不同,可能是一个键值,指向厂商的全局注册表
以上注解标注在bean class类之上,表示注册一个引用,要通过lookup查找,如果用于bean class的setter方法或数据成员(类型是EJB的成员),却表示直接注入

通过XML指定远程EJB引用
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>//EJB名
        <ejb-ref>
            <ejb-ref-name> com.titan.travelagent.TravelAgentBean/payment </ejb-ref-name>注册名
            <ejb-ref-type>Session</ejb-ref-type>    EJB类型有Session、Entity
            <remote>com.tian.Processpayment.ProcessPaymentRemote</ remote>    远程接口
            <ejb-link>ProcessPaymentBean</ejb-link>实现接口的EJB,如果接口有多个实现类必须配置
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>payment</injection-target-name>也可以使用processPayment
            </injection-target>
        </ejb-local-ref>
    </session>
</enterprise-beans>

通过XML指定本地EJB引用
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <ejb-local-ref>
            <ejb-ref-name> com.titan.travelagent.TravelAgentBean/payment</ejb-ref-name>注册名
            <ejb-ref-type>Session</ejb-ref-type>     EJB类型有Session、Entity
            <local>com.tian.Processpayment.ProcessPaymentLocal</local>    本地接口
            <ejb-link>ProcessPaymentBean</ejb-link>     与注解beanName等价,表示引用的EJB名。
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>payment</injection-target-name>也可以使用processPayment
            </injection-target>
        </ejb-local-ref>
    </session>
</enterprise-beans>

EJB名称的二义性和重载
对于某个特定的EJB JAR部署包而言,部署描述文件中的<ejb-name>元素及任何@Stateless或@Stateful注解的name属性必须是全局唯一的。但是对于同一个.ear文件的不同EJB-JAR部署包内,EJB名称是可以重复的,这了区分这些EJB,可以使用扩展语法:@EJB(beanName=”inventory-ejb.jar#InventoryEJB”) InventoryLocal inventory;

EntityManagerFactory类型的引用
在应用服务器对ENC进行配置或将EntityManagerFactory注入到EJB中之后,应用服务器会为你管理EntityManagerFactory实例的生命周期。定义引用的方式:
@javax.persistence.PersistenceUnit(name=”persistence/TitanDB”,//JNDI ENC名
    unitName=”TitanDB”)//persistence.xml文件中声明的persistence unit名称
该注解标注bean class时,表示不直接注入,如果标注在bean class的setter方法或数据成员上,表示直接注入,如:
@ PersistenceUnit(unitName=”crmDB”)private EntityManagerFactory crm;
如果要引用多个persistenceunit,要使用@PersistenceUnits注解。

通过XML指定EntityManagerFactory类型的引用
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <persistence-unit-ref>
            < persistence-unit-ref-name>persistence/TitanDB</persistence-unit-ref-name>注册名
            persistence.xml文件声明的persistence unit名
            < persistence-unit-ame>TitanDB</ persistence-unit-ame>
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>ships<injection-target-name>
            </injection-target>
        </ persistence-unit-ref >
    </session>
</enterprise-beans>

Persistence Unit名称的作用域及重载问题
可以在不同的地方声明persistence unit,它可以定义在EJB-JAR、EAR/lib目录下的JAR或WAR文件中。如果定义的persistence unit有重名,可以通过这个扩展语法访问:@ PersistenceUnit(unitName=”inventory.jar#InventoryDB”)

EntityManager类型的引用
当将EntityManager注册到JNDI ENC或注入到EJB时,EJB容器会对EntityManager所依赖的persistence contect具有完全的控制权(控制它的生命周期),注册方式与EntityManagerFactory很相似,如:
@PersistenceContext(name”persistence/TitanDB”//JNDI ENC名
    unitName=”TitanDB”//与peristence.xml文件中声明的peristence unit名称相同
    type=PersistenceContextType.EXTENDED)//表示extended persistence context(方法间事务,只用于        //stateful session),还有一个取值TRANSACTION。
可以用于标注bean class,当标注在bean class的setter方法或数据成员上时,表示直接注入,如:
@ PersistenceContext(unitName=”crmDB”)private EntityManager crm;

通过XML指定EntityManager类型的引用
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <persistence-context-ref>
            <persistence-context-ref-name>persistence/TitanDB</persistence-context-ref-name>名
            persistence.xml文件声明的persistence unit名
            <persistence-context-ame>TitanDB </persistence-context-ame>
            <persistence-context-type>EXTENDED</persistence-context-type>
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>ships<injection-target-name>
            </injection-target>
        </ persistence- context -ref >
    </session>
</enterprise-beans>

资源类型的引用
外部资源同样会被映射到JNDI ENC名字空间中的名称上,并且可以有选择地注入到bean实例的数据成员或setter方法中,被引用的外部资源类型可以是:javax.sql.DataSource、javax.jms.ConnectionFactory、javax.jms.QueueConnectionFactory、javax.jms.TopicConnectonFactory、javax.mail.Session、java.net.URL、javax.resource.cci.ConnectionFactory以及由JCA资源适配器定义的其他类型。下面以javax.sql.DataSource为例。

@javax.annotation.Resource(annotation:注解)
@ Resource注解除了用来引用外部资源,还可以用来引用JMS消息的目标地址、JNDI的环境注册项、EJBContext,以及其他Java EE的核心服务。

@ Resource(name=”jdbc/OracleDB”,//JNDI ENC名
    type=javax.sql.DataSource,//引入的类别
    authenticationType=AuthenticationType.APPLICATION,
    //认证方式,有容器认证(取值CONTAINER,容器根据部署的用户名和密码进行认证)和程序自行认证
    //(getConnection时要提供用户名和密码)
    shareable=true,//多个EJB在同一事务中是否可以使用相同的资源,使用相同的资源连接,以提高性能
    mappedName=”java:/DefaultDS”)//外部资源的厂商专用标识符,大多数情况,它的取值等价于一个                                    //全局JNDI名。
如果要引用多个资源,可以使用@javax.annotation.Resources注解

通过XML指定资源类型的引用
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <resource-ref>
            <res-ref-name>jdbc/OracleDB</res-ref-name>ENC注册名
            <res-type>javax.sql.DataSource</res-type>类名
            <res-auth>Container</res-auth>
            <mapped-name>java:/DefaultDS</mapped-name>
            java:/DefaultDS是一个全局JNDI中定义的一个数据源,数据源的配置请查询相关书籍
          
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>oracle<injection-target-name>
            </injection-target>
        </resource-ref >
    </session>
</enterprise-beans>

资源环境和受管对象
资源环境注册项可以引用包含受管对象的资源,受管对象是一种在部署期间被配置到容器中,并在运行期间由容器负责管理的资源,它的配置书中没有给出例子。资源环境注册项也可可以用于诸如:javax.transaction.Usertransaction和javax.transaction.TransactionSynchronizationRegistry服务,这时定义authenticationType和shareable 是非法的。
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <resource-env-ref>
            <resource-env-ref-name>jdbc/OracleDB</resource-env-ref-name>//ENC注册名
            <resource-env-ref-type>javax.transaction.Usertransaction</resource-env-ref-type>类
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>utx<injection-target-name>
            </injection-target>
        </resource-env-ref >
    </session>
</enterprise-beans>

环境注册项还可以用来配置String、Integer、Long、Double、Float、Byte、Boolean和Short这些包装类型的常量。
<enterprise-beans>
    <session>
        <ejb-name>ProcessPaymentBean</ejb-name>
        <env-entry>
            <env-entry-name>minCheckNumber</env-entry-name>ENC注册名
            <env-entry-type>java.lang.Integer</env-entry-type>类名
            <env-entry-value>2000</env-entry-value>常量值,这种引用几乎都是用XML来配置的
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.processpayment.ProcessPaymentBean
                </injection-target-class>
                <injection-target-name>minCheckNumber<injection-target-name>
            </injection-target>
        </env-entry>
    </session>
</enterprise-beans>

消息目标地址类型的引用
在JNDI ENC中注册的消息目标地址引用指向JMS的主题或队列。
@Resource(name=”jms/TicketTopic”,//ENC名
    type=javax.jms.Topic,//类型,还可以是队列(javax.jms.Queue)
    mappedName=”topic/TicketTopic”)//全局的厂商专用标识符
注意,使用注解无法设置目标地址的连接(message-destincton-link)
等价XML
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <message-destination-ref>
            <message-destination-ref-name>jms/TicketTopic</message-destination-ref-name>注册名
            <message-destination-type>javax.jms.Topic</message-destination-type>消息类型
            从目标地址收消息还是向其发消息
            <message-destination-usage>Produces</message-destination-usage>
            <message-destination-link>Distributor </message-destination-link>消息分发地址
            <mapped-name> topic/TicketTopic </mapped-name>
            topic/TicketTopic表示主题,它的配置请找相关书籍,原书练习中只讲到配置队列
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>ticketTopic <injection-target-name>
            </injection-target>
        </ message-destination-ref >
    </session>
</enterprise-beans>

Web Service类型的引用
在JNDI ENC中注册的web service引用指向服务的接口或服务的终端接口。19章有详细介绍
<enterprise-beans>
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        <service-ref>
            <service-ref-name>service/ChargeItProcessorService</service-ref-name>ENC注册名
          <service-interface>com.charge_it.ProcessorService</service-interface>JAX-RPC服务接口
            <wsdl-file>META-INF/wsdl/ChargeItProcesor.wsdl</wsdl-file> WSDL文件位置
            <jaxrpc-mapping-file>META-INF/mapping.xml </jaxrpc-mapping-file> JAX-RPC映射文件
            <service-qname>chargeIt:ProcessorService</service-qname>与WSDL文件定义的服务名一致
            <mapped-name>webservice/ChargeItProcessorService</mapped-name>
            webservice/ChargeItProcessorService映射应用服务器全局注册项
            <injection-target>        要直接注入时才用这个配置
                <injection-target-class>
                    com.titan.travelagent.TravelAgentBean
                </injection-target-class>
                <injection-target-name>chargeService <injection-target-name>
            </injection-target>
        </ message-destination-ref >
    </session>
</enterprise-beans>
分享到:
评论

相关推荐

    技术专栏 _ 深入理解JNDI注入与Java反序列化漏洞利用.pdf

    在深入探讨JNDI注入与Java反序列化漏洞之前,我们需要对几个关键概念有所了解,这包括Java远程方法调用(RMI)、Java名称目录接口(JNDI)、Java远程消息交换协议(JRMP)、以及序列化和反序列化。 RMI是Java环境中...

    Spring 三种依赖注入方式.doc

    Spring 三种依赖注入方式 Spring 框架中提供了多种依赖注入方式,其中最常用的三种依赖注入方式分别是接口注入、设值注入和构造函数注入。下面,我们将分别对这三种依赖注入方式进行详细的介绍和分析。 一、接口...

    jndi所依赖的jar包

    1. `fscontext.jar`:这是一个提供文件系统上下文(FileSystemContext)的JAR文件,它使得JNDI能够与本地文件系统进行交互。通过这个库,开发者可以使用JNDI接口来查找和操作文件系统中的资源,就像处理远程对象一样...

    JNDI:JNDI注入利用工具

    JNDI注入利用工具 介绍 本项目为JNDI注入利用工具,生成JNDI连接并启动初始化相关服务,可用于Fastjson,Jackson等相关突破的验证。 本项目是基于welk1n的 ,在此项目的基础服务框架上,重新编写了攻击利用代码,...

    2022年EJB 3.0开发指南之依赖注入Java教程.docx

    依赖注入(Dependency Injection,简称DI)是Java编程中一种重要的设计模式,特别是在企业级Java应用(Enterprise JavaBeans,EJB)3.0版本中得到了广泛的应用。依赖注入的核心思想是解耦,它允许开发者在不修改代码...

    JNDI注入学习1

    **JNDI注入详解** Java Naming and Directory Interface (JNDI) 是Java应用程序用来查找和管理网络资源的接口。它不依赖于特定的目录服务,而是通过服务提供者接口(SPI)来支持多种不同的目录服务,如LDAP、DNS等...

    jndi-1_2_1.zip_jndi_jndi-1.2.1.jar

    6. lib 文件夹可能包含了依赖的库文件,这些库可能与其他服务或组件的集成有关。 总的来说,这个JNDI-1.2.1开源包为Java开发者提供了访问和管理命名服务的能力,通过其API可以实现查找和绑定对象,进行目录服务操作...

    jndi-tool JNDI服务利用工具

    总结来说,"jndi-tool"是一个强大的JNDI服务利用工具,适用于评估和利用与Fastjson和Log4j漏洞相关的RCE风险。它利用RMI和LDAP协议,可以在高版本JDK环境下运行,为安全专业人士提供了一种有效测试环境安全性的手段...

    spring依赖注入知识点分享

    Spring 依赖注入知识点分享 在本篇文章中,我们将详细介绍 Spring 依赖注入的知识点,并提供相关的代码内容。 什么是 IoC IoC(Inversion of Control),即控制反转,是一种软件设计模式。它将对象之间的依赖关系...

    JNDI-Injection-Exploit-1.0-SNAPSHOT-all

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

    JNDIDemo 以及相关文档

    8. **JNDI与EJB和JDBC**:在Enterprise JavaBeans (EJB) 中,JNDI用于查找和注入EJB实例。在Java Database Connectivity (JDBC) 中,数据源通常通过JNDI查找来获取,这样可以轻松地在不同环境中配置数据库连接。 9....

    JNDIExploit-用于 JNDI注入利用的工具

    一款用于 JNDI注入利用的工具,大量参考/引用了Rogue JNDI项目的代码,支持直接植入内存shell,并集成了常见的bypass 高版本JDK的方式,适用于与自动化工具配合使用。 使用 java -jar JNDIExploit.jar -h 查看参数...

    rogue-jndi:用于JNDI注入攻击的恶意LDAP服务器

    用于JNDI注入攻击的恶意LDAP服务器。 描述 该项目包含LDAP和HTTP服务器,用于利用默认情况下不安全的Java JNDI API。 为了执行攻击,您可以在本地启动这些服务器,然后在易受攻击的客户端上触发JNDI解析,例如: ...

    JNDI简介与SPI实现

    绑定是将一个名字与一个对象关联的过程,通过这个名字,我们可以获取到对应的对象。 JNDI操作主要包括以下步骤: 1. 创建初始上下文(Initial Context):这是访问JNDI服务的第一步,通常使用`InitialContext()`...

    JNDI示例整合SSH

    在整合JNDI时,可能需要在Struts配置文件(struts-config.xml或struts2的struts.xml)中注入依赖的服务或数据源。 2. **Spring:** Spring作为IoC/DI容器负责组件的管理和装配。可以利用Spring的JNDI_lookup标签...

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

    描述中的内容与标题相同,没有提供额外的信息,但我们可以推测这可能是一个研究、教育或安全审计用途的工具包,用于理解和防范JNDI注入攻击。 标签"java 网络安全"进一步确认了这个主题是关于Java编程语言在网络...

    Tomcat中JNDI原理

    #### 二、JNDI与Tomcat ##### 2.1 JNDI概述 JNDI提供了一种查找和定位应用程序所用资源的标准化方式,这些资源包括数据库连接、消息队列、EJBs、对象引用等。JNDI的核心概念包括: - **命名**:使用名字来标识...

    jndi 反射 耦合

    减少耦合的方法包括使用接口、依赖注入、模块化设计等。 综合来看,"jndi 反射 耦合"这三个概念在实际开发中都扮演着关键角色。理解并合理运用JNDI可以提高程序的灵活性,掌握反射能够实现动态编程,而降低耦合性则...

    jndi-1.2.1.jar.zip

    `jndi-1.2.1.jar` 是包含JNDI 1.2.1实现的库文件,它是Java应用程序使用JNDI功能的必要依赖。开发者在项目中引入这个库,即可利用JNDI 1.2.1提供的强大功能,实现命名和目录服务的灵活接入。 总结来说,JNDI 1.2.1...

Global site tag (gtag.js) - Google Analytics