什么是JNDI
J2SE,是java2的标准版,主要用于开发桌面的应用程序。
J2SE包含了构成java语言核心的类:数据库连接、接口定义、输入输出、网络编辑等。
J2EE, 是java2的企业版,主要用于分布式的网络程序的开发。
j2ee包含j2se中的类,还包含用于开发企业级应用的类,也包含企业应用中很多的API。例如:JDBC、JNDI、EJB等。
不少专家认为,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识
JNDI概念
JNDI全称Java Naming and Directory Interface 翻译过来就是Java命名和目录接口。这个概念搞出来就是为了方便人们来记录一些不容易记录都内容。有点类似于域名和ip的映射。所以如果要深入的学可能会被绕进去,现在你可以简单的理解为他是一个字典,给不同的对象和属性(value)取名(key)。到时候好找出来用。
JNDI作用
网上比较经典的例子就是JDBC连接数据库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class Scr { public static void main(String[] args) { String JDBC_DRIVER = "com.mysql.jdbc.Driver"; String JDBC_URL = "jdbc:mysql://localhost:3306/tt?useSSL=false&serverTimezone=UTC";
String USER = "root"; String PASS = "admin123"; Connection connection = null;
Statement statement = null; try {
Class.forName(JDBC_DRIVER);
connection = DriverManager.getConnection(JDBC_URL,USER,PASS);
statement = (Statement) connection.createStatement();
String sql = "SELECT name,sex FROM aa";
ResultSet rSet = statement.executeQuery(sql);
while(rSet.next()) {
String get_name = rSet.getString("name"); String get_sex = rSet.getString("sex");
System.out.println("名字:"+get_name); System.out.print("性别:"+get_sex); }
rSet.close(); statement.close(); connection.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }
|
可以看到这是我们初学java时的代码,因为那时候我们都是一个人开发整个系统,如果有一天一家公司有成百上千的人开发同一套系统呢?是不是不应该所有的程序员都知道这个账号密码、url格式、后端的实现逻辑、数据库类型等等?这就是Java编程中重要的思想:解藕。
解藕当然呢不只JNDI这一种方式。很多时候封装的越来越细小也算是解耦。但是JNDI提供了这种更方便的解藕概念。
比如上面这个链接数据库的代码我可以用JNDI这样做:
定义一个xml模版,mysql.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <jndi-name>mysqlconfigsouce</jndi-name> <connection-url>jdbc:mysql://localhost:3306/</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>root</user-name> <password>passwd</password> <exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter </exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>
|
然后我们在程序中引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Connection conn=null; try { Context ctx=new InitialContext(); Object datasourceRef=ctx.lookup("java:mysqlconfigsouce"); DataSource ds=(Datasource)datasourceRef; conn=ds.getConnection(); ...... c.close(); } catch(Exception e) { e.printStackTrace(); } finally { if(conn!=null) { try { conn.close(); } catch(SQLException e) { } } }
|
当然JNDI只是一个概念,具体实现还有rmi和ldap等协议参与其中。上面只是举个例子。
这里补充一点:正如我们第一节所说的,JNDI是一个类似域名和ip的对应机制,那javax.naming 的包中就提供了Context接口,最重要的
就是两个方法:
1、 void bind( String name , Object object )
绑定
2、Object lookup( String name )
获取
JNDI在JAVA应用程序中的位置:
![image-20230130163311234](/Users/geez/Library/Application Support/typora-user-images/image-20230130163311234.png)
可以看到JNDI在应用程序和底层服务LADP、DNS、RMI等等之间,可以理解为JNDI封装了一套管理命名和目录的接口,通过JNDI我们可以使用rmi、LDAP等各种协议的命名和目录服务。当然如果JNDI的检索参数被控制,就会引发重大安全问题,这就是后面要写的JNDI注入的问题。
———–太忙了先不写了———
要分析的漏洞:fastjson、log4j、shiro、weblogic那些