1 两种jbdc驱动,kerberos认证的区别描述
1-1 hive-jdbc驱动与kerberos认证
对于hive-jdbc驱动,kerberos认证的代码块与Connection实例化的代码块,耦合性不强,保证执行的时序性即可。(kerberos认证在前,Connection实例化在后),如下图所示。
代码如下。
// 先执行kerberos认证的代码块
// 1. login use keytab
System.setProperty("java.security.krb5.realm", "XXX.COM");
System.setProperty("java.security.krb5.kdc", "kdcXXX");
Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "Kerberos");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab");
// 接着执行Connection实例化的代码块
try {
Class.forName(driverName);
Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
String sql = "show databases;";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString(1));
}
} catch (Exception e) {
e.printStackTrace();
}
1-2 impala-jdbc驱动与kerberos认证
对于impala-jdbc驱动,kerberos认证的代码块与Connection实例化的代码块,两者强耦合,除了保证执行的时序性(kerberos认证在前,Connection实例化在后),还要求在doAs函数,创建Connection,如下图所示。
代码如下所示。
// kerberos认证的代码块
// 1. login use keytab
System.setProperty("java.security.krb5.realm", "XXX.COM");
System.setProperty("java.security.krb5.kdc", "kdcXXX");
Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "Kerberos");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab");
// 在UserGroupInformation的doAs函数中实现Connection的创建
// 2. create impala jdbc connection
Class.forName(JDBCDriverName);
conn = (Connection) ugi.doAs(new PrivilegedExceptionAction<Object>() {
public Object run() {
Connection tcon = null;
try {
tcon = DriverManager.getConnection(connectionUrl);
} catch (SQLException e) {
e.printStackTrace();
}
return tcon;
}
});
// 3. execute query using conn
2 kerberos认证与连接池集成方案
对比上述两段代码,当引入连接池技术来管理Connection时。对不同驱动分别说明之。
2-1 hive-jdbc,kerberos认证与连接池集成方案
对hive-jdbc情况,比较简单,满足两个代码块执行的时序性即可。即确保在连接池实例化前,执行kerberbos认证的代码块。具体实现方法:① spring bean中的depends-on标签(见参考文献[3])。② 配置Listener。见参考文献[2])。
这种情况,不是本文章的重点,这里不对它具体展开。
2-2 impala-jdbc,kerberos认证与连接池集成方案
考虑到Connection创建是连接池类内部的函数。而kerberos认证代码块是对Connection创建这一过程本身进行包裹。即kerberos认证的代码块,与连接池类内部的函数创建Connection的代码块,两者强耦合。如下图所示。
考虑到上述情况,如何打开连接池类的封装,对连接池类内部的getConnection函数加上kerberbos认证的逻辑?
换言之,对如何对一个类的方法进行增强?
最朴素的路子是继承这个类,然后覆写这个类中的目标增强方法。
以Druid连接池为例,创建一个类继承DruidSource,对所有getConnection相关的几个函数重写,把kerberbos认证相关的代码块嵌入到该函数里面。这样可以通过kerberbos认证,并返回Connection。
public class DruidDataSourceWrapper extends DruidDataSource {
// 创建一个函数,指向父类的getConnection(long)方法
public DruidPooledConnection superGetConnection(long maxWaitMillis) throws SQLException {
return super.getConnection(maxWaitMillis);
}
/**
* 覆写父类的getConnection(long)方法,在父类的getConnection(long)方法外面包裹上kerberbos认证的代码块
*/
@Override
public DruidPooledConnection getConnection(final long maxWaitMillis) throws SQLException {
// kerberos认证的代码块
// 1. login use keytab
System.setProperty("java.security.krb5.realm", "XXX.COM");
System.setProperty("java.security.krb5.kdc", "kdcXXX");
Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "Kerberos");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab");
// 在UserGroupInformation的doAs函数中实现Connection的创建
// 覆写父类的getConnection(long)方法,在方法外面包裹上kerberbos认证的代码块
DruidDataSourceWrapper _this = this;
Connection conn = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
public Connection run() {
Connection tcon = null;
try {
// 父类的getConnection(long)方法
tcon = _this.superGetConnection(maxWaitMillis);
} catch (SQLException e) {
e.printStackTrace();
}
return tcon;
}
});
// 返回connection
return conn;
}
}
在与spring框架集成时,在连接池相关的xml配置文件中,关于数据库连接池,class类路径指向我们封装的类路径即可。
<bean id="dataSource" class="com.tools.pool.DruidDataSourceWrapper">
<property name="driverClassName" value="com.cloudera.impala.jdbc41.Driver"/>
<property name="url" value="your_url"/>
<property name="username" value="your_username"/>
<property name="password" value="your_password"/>
</bean>
2-3集成方案中可能存在的技术点
上述涉及到对一个类的函数功能进行增强,有点连接池类被final修饰,不能被继承。有没有其它的方法对不能继承的类进行增强呢?答案是存在的,是装饰者模式与动态代理模式。
举个例子:c3p0连接池,比较适合装饰者模式对getConnection函数进行增强。
对于Java中增强一个类的几种方法,具体参考文献[6]、[7]。
3 参考文献
[1] https://blog.csdn.net/tlqfree... (windows环境 java jdbc 连接impala (kerberos认证) - 空谷幽兰草堂 - CSDN博客)
[2] https://blog.csdn.net/zhanglu... (springmvc集成kerberos认证hive jdbc连接 - 张小竟 - CSDN博客)
[3] http://www.aboutyun.com/forum... (hive + kerberos spring 配置 DruidDataSource 数据库连接池-Hive-about云开发)
[4] https://www.cnblogs.com/zhish... (Spring depends-on介绍)
[5] https://stackoverflow.com/que... (authentication - Error when connect to impala with JDBC under kerberos authrication - Stack Overflow)
[6] https://blog.csdn.net/friday_... (Java中增强一个类的几种方法 - friday_PJ的博客 - CSDN博客)
[7] https://www.cnblogs.com/xuzha... (对java方法进行功能增强的三种方法)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。