本文主要介绍基于 Kerberos 环境下,如何使用 Java 远程连接 Hive 。
一、创建自定义 Principal 与 keytab
虽然可以使用 Hive 服务本身的 Principal 与 keytab 来连接 Hive ,但使用服务本身的 principal 不具有普遍性,所以还是建议使用自定义的 Principal 。
有两种场景,一种是在 Kerberos KDC 所在的主机上,一种是非 Kerberos KDC 所在的主机。以下分这两种场景来创建 Principal 和 Keytab 。
在 kerberos kdc 所在的主机上,在 root 用户下使用 kadmin.local 进入:
1 2 3 4 5 6 7 8 9 10 11 12 13
| # 为linux增加liuyzh用户 useradd liuyzh # 创建principal,randkey参数会自动生成随机密码 addprinc -randkey liuyzh/node71.xdata@EXAMPLE.COM # 验证principal是否被创建 getprinc liuyzh/node71.xdata@EXAMPLE.COM # 为liuyzh/node71.xdata@EXAMPLE.COM创建principal ktadd -norandkey -k /etc/security/keytabs/liuyzh.service.keytab liuyzh/node71.xdata@EXAMPLE.COM # 验证 kinit -kt /etc/security/keytabs/liuyzh.service.keytab liuyzh/node71.xdata@EXAMPLE.COM # 查看kerberos认证缓存 klist # 此时liuyzh用户就代理了root用户操作。
|
在非 kerberos kdc 主机上,在 root 用户下使用 kadmin 进入:
1 2 3 4 5 6 7 8 9 10 11
| # 在非 kerberos kdc 所在的主机,首先需要验证身份:kinit xxx/admin@EXAMPLE.COM,输入明文密码 kinit admin/admin@EXAMPLE.COM # 输入明文密码,例如:123456 # 创建principal,randkey参数会自动生成随机密码 addprinc -randkey liuyzh/node72.xdata@EXAMPLE.COM # 为liuyzh/node72.xdata@EXAMPLE.COM创建keytab,在kadmin模式下创建keytab时,需要去除-norandkey,默认为-randkey ktadd -k /etc/security/keytabs/liuyzh.service.keytab liuyzh/node72.xdata@EXAMPLE.COM # 验证 kinit -kt liuyzh.service.keytab liuyzh/node72.xdata@EXAMPLE.COM klist # 此时liuyzh用户就代理了root用户操作。
|
注意:keytab 文件一般要配置执行用户的只读权限,还要注意记得配置 Windows 的 主机名与 ip 映射。
二、拷贝 krb5.conf 与 keytab 文件
Java 程序会用到 krb5.ini 和对应的 principal 文件,其中 krb5.ini 文件的内容是 linux 上 /etc/krb5.conf 文件里面的部分内容,内容如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [libdefaults] renew_lifetime = 7d forwardable = true default_realm = EXAMPLE.COM ticket_lifetime = 24h dns_lookup_realm = false dns_lookup_kdc = false
[realms] EXAMPLE.COM = { admin_server = node71.xdata kdc = node71.xdata }
|
keytab 文件为上边创建 liuyzh/node71.xdata@EXAMPLE.COM 对应的 liuyzh.service.keytab 。principal 的主体部分(liuyzh)为代理用户,liuyzh.service.keytab 为密钥文件。
将 krb5.ini 和 keytab 文件从 Linux 上拷贝到项目工程的根目录下。
三、Java 代码示例
1、添加 pom 依赖:
1 2 3 4 5 6
| <!-- Hive2.1.0 --> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-jdbc</artifactId> <version>2.1.0</version> </dependency>
|
2、jdbc url 的两种写法
通过 jdbc 来连接 Hive ,jdbc 的写法有两种:
基于 Kerberos 环境的 Hive jdbc url 需要特别注意,格式如下:
这里的 principal 是固定不变的,其指的 hive 服务所对应的 principal ,而不是用户所对应的 principal 。
3、初始化连接代码
初始化连接的逻辑里面,需要指定如下配置:
- hadoop.security.authentication
- java.security.krb5.conf
- 登陆时指定 principal 和 keytab
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public void getConnection() { Configuration conf = new Configuration(); conf.set("hadoop.security.authentication", "Kerberos"); System.setProperty("krb5_ini", System.getProperty("user.dir") + "\\krb5\\krb5.ini"); System.setProperty("hive_keytab", System.getProperty("user.dir") + "\\krb5\\liuyzh.service.keytab"); System.setProperty("java.security.krb5.conf", System.getProperty("krb5_ini")); UserGroupInformation.setConfiguration(conf); try { UserGroupInformation.loginUserFromKeytab("liuyzh/node71.xdata@EXAMPLE.COM", System.getProperty("hive_keytab")); } catch (IOException e) { e.printStackTrace(); } try { conn = DriverManager.getConnection(url2); } catch (SQLException e) { e.printStackTrace(); } }
|
4、列举数据库内的所有表
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| private static String url = "jdbc:hive2://node72.xdata:10000;principal=hive/node72.xdata@EXAMPLE.COM"; private static String url2 = "jdbc:hive2://node71.xdata:2181,node72.xdata:2181,node73.xdata:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2;principal=hive/node72.xdata@EXAMPLE.COM"; private static Connection conn = null; private static PreparedStatement ps = null; private static ResultSet rs = null;
@Test @Before public void getConnection() { Configuration conf = new Configuration(); conf.set("hadoop.security.authentication", "Kerberos"); System.setProperty("krb5_ini", System.getProperty("user.dir") + "\\krb5\\krb5.ini"); System.setProperty("hive_keytab", System.getProperty("user.dir") + "\\krb5\\liuyzh.service.keytab"); System.setProperty("java.security.krb5.conf", System.getProperty("krb5_ini")); UserGroupInformation.setConfiguration(conf); try { UserGroupInformation.loginUserFromKeytab("liuyzh/node71.xdata@EXAMPLE.COM", System.getProperty("hive_keytab")); } catch (IOException e) { e.printStackTrace(); } try { conn = DriverManager.getConnection(url2); } catch (SQLException e) { e.printStackTrace(); } }
@Test public void showTables() { try { ps = conn.prepareStatement("use default"); ps.execute(); rs = ps.executeQuery("show tables"); while (rs.next()) { System.out.println(rs.getString(1)); } } catch (SQLException e) { e.printStackTrace(); } }
@Test @After public void closeConnect() { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
|
四、总结
其实,基于kerberos连接Hive只需要改动初始化连接部分就可以,需要准备:
- 设置 principal 和相对应的 keytab
- 指定 java.security.krb5.conf 配置
- 指定 hadoop.security.authentication 为 kerberos 认证
其它代码还是 外甥打灯笼 – 照旧 。
更多的基于kerberos的hive操作,已经上传到 github ,地址为:
https://github.com/841809077/hdp2project/blob/master/src/main/java/com/hdp2/project/hive/HiveOperateTest.java