欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

java如何通过Kerberos认证方式连接hive,

来源: javaer 分享于  点击 23097 次 点评:265

java如何通过Kerberos认证方式连接hive,


目录
  • Java实现Kerberos认证
    • 主要方法
    • 依赖
    • 示例
    • 续期
  • 连接hive
    • 遇到的问题
      • 分析
      • 解决方式
    • 扩展
      • 思考
        • 总结

          在数据源管理功能中,需要适配mysql、postgresql、hive等数据源。

          mysql和postgresql连接方式一致,只需要驱动和jdbcurl即可,而hive背后是大数据集群,多采用Kerberos的方式保护集群环境,要想与大数据集群正常交互,需要经过kdc认证获取ticket,因此获取hive连接前需要先通过Kerberos认证

          Java实现Kerberos认证

          主要方法

          # 从keytab文件中加载用户标识并登录
          org.apache.hadoop.security.UserGroupInformation#loginUserFromKeytab

          依赖

          kerberos相关配置文件:krb5.conf、keytab文件从大数据集群管理员那获取

          依赖:hive-jdbc:3.1.3(hive安装目录中带有该驱动包,可查看使用的版本)、hadoop-common:3.3.6,版本需和hive服务版本一致,在springboot3的框架下需要排除以下依赖,否则启动报错

          <dependency>
              <groupId>org.apache.hive</groupId>
              <artifactId>hive-jdbc</artifactId>
              <version>${hive.jdbc.version}</version>
              <exclusions>
                  <exclusion>
                      <artifactId>HikariCP-java7</artifactId>
                      <groupId>com.zaxxer</groupId>
                  </exclusion>
                  <exclusion>
                      <artifactId>javax.servlet.jsp</artifactId>
                      <groupId>org.glassfish.web</groupId>
                  </exclusion>
                  <exclusion>
                      <artifactId>jetty-runner</artifactId>
                      <groupId>org.eclipse.jetty</groupId>
                  </exclusion>
              </exclusions>
          </dependency>
          <dependency>
              <groupId>org.apache.hadoop</groupId>
              <artifactId>hadoop-common</artifactId>
              <version>${hadoop.version}</version>
              <exclusions>
                  <exclusion>
                      <artifactId>commons-lang3</artifactId>
                      <groupId>org.apache.commons</groupId>
                  </exclusion>
                  <exclusion>
                      <artifactId>curator-client</artifactId>
                      <groupId>org.apache.curator</groupId>
                  </exclusion>
              </exclusions>
          </dependency>

          示例

          String confPath = "\xxx\krb5.conf";
          String keytabPath = "\xxx\hive.service.keytab";
          String principal = "hive/xxx@xxx";
          
          System.setProperty("java.security.krb5.conf", confPath);
          //System.setProperty("sun.security.krb5.debug", "true");
          //System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
          Configuration configuration = new Configuration();
          configuration.set("hadoop.security.authentication", "KERBEROS");
          
          UserGroupInformation.setConfiguration(configuration);
          try {
              UserGroupInformation.loginUserFromKeytab(principal, keytabPath);
          } catch (IOException e) {
              log.error("authKerberos exception", e);
              throw new BizException("kerberos认证失败");
          }

          除了上述方式外,也可采用JAAS可插拔的认证模块进行Kerberos认证

          续期

          Kerberos的ticket存在有效期,过期后导致服务不可用

          Kerberos ticket存在两种有效期,ticket timelife(票据生命周期)、renewable lifetime(可再生周期)

          • ticket的时间超过ticket lifetime时,该ticket将不可用
          • 在renewable lifetime的时间内,可以对即将过期的ticket进行续期,超过renewable lifetime时间后,无法续期
          • 例如kerb5.conf文件中的配置:ticket_lifetime = 24h renewable_lifetime = 7d,则在登录后的24小时内,可以对即将过期的ticket进行续期,距第一次登录7天后,将不再允许续期

          UserGroupInformation提供了认证续期的私有方法UserGroupInformation#reloginFromKeytab(boolean),该方法有两个触发入口UserGroupInformation#checkTGTAndReloginFromKeytabUserGroupInformation#reloginFromKeytab()

          值得注意的是

          UserGroupInformation#loginUserFromKeytab

          方法中会开启异步任务,定时触发续期方法,触发的续期方法即是

          UserGroupInformation#reloginFromKeytab()

          向线程池中提交续期的任务

          也可以自定义触发续期的逻辑, 定期触发

          UserGroupInformation.getLoginUser().checkTGTAndReloginFromKeytab()

          连接hive

          Kerberos认证之后,使用hive-jdbc连接hive,之后与连接mysql、pg的方式无异,使用DriverManager或数据源连接池Hikari皆可

          遇到的问题

          一开始选择hadoop-common的版本是3.1.3,执行Kerberos认证时报错

          KerberosUtil无法访问sun.security.krb5.Config(它在java.security.jgss模块中)。

          分析

          本项目采用的框架是spring boot3版本,最低要求的jdk版本是17,而Java在9之后引入了模块化机制,模块必须显式声明他们要到导出的包以供其他模块使用。

          但是java.security.jgss模块的module-info.class文件中并未声明

          解决方式

          1.在JVM的启动参数上增加以下参数

          --add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED

          2.升级hadoop-common版本到3.3.6

          在该版本中KerberosUtil并未通过反射访问sun.security.krb5.Config

          • hadoop-common:3.1.3版本的KerberosUtil

          hadoop-common:3.3.6版本的KerberosUtil

          扩展

          利用JAAS机制认证Kerberos,不再使用UserGroupInformation进行认证

          增加一个配置文件gss-jaas.conf

          com.sun.security.jgss.initiate{
             com.sun.security.auth.module.Krb5LoginModule required
             doNotPrompt=true
             useTicketCache=true
             useKeyTab=true
             renewTGT=true
             debug=true
             ticketCache="/kerberos-tmp/krb5cc_1000"
             keyTab="D:\\xxxx\\hive.service.keytab"
             principal="hive/xxxx@xxxx";
           };
          private void authKerberos1() {
              // 指定gss-jaas.conf文件路径
              System.setProperty("java.security.auth.login.config", "D:\\xxx\\gss-jaas.conf");
              // System.setProperty("sun.security.jgss.debug", "true");
              System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
              String confPath = "D:\\xxxx\\krb5.conf";
              System.setProperty("java.security.krb5.conf", confPath);
          }

          思考

          有时我们开发的系统是要部署到客户现场使用,而客户现场使用的hive版本和司内环境使用的版本可能不同。一般在程序开发时使用的依赖版本皆是定义在pom文件中,一旦打包之后依赖的版本就是固定的。因此需要考虑程序可适配不同的hive-jdbc版本,能够动态加载不同版本的hive-jdbc,或者在项目启动时可以指定额外的hive-jdbc驱动包

          • 使用类加载器在程序运行时动态从指定路径读取并加载指定的驱动jar包
          URLClassLoader loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
          Class.forName(driverName, true, loader);
          • 在项目启动时能够将指定的目录中的jar包放到类路径中

          总结

          以上为个人经验,希望能给大家一个参考,也希望大家多多支持3672js教程。

          您可能感兴趣的文章:
          • java实现往hive 的map类型字段写数据
          • Java API如何实现向Hive批量导入数据
          • 大数据 java hive udf函数的示例代码(手机号码脱敏)
          • Java JDBC连接Kerberos认证的HIVE和Impala方式
          相关栏目:

          用户点评