当前位置: 代码网 > it编程>编程语言>Java > java如何通过Kerberos认证方式连接hive

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

2025年02月13日 Java 我要评论
在数据源管理功能中,需要适配mysql、postgresql、hive等数据源。mysql和postgresql连接方式一致,只需要驱动和jdbcurl即可,而hive背后是大数据集群,多采用kerb

在数据源管理功能中,需要适配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包放到类路径中

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com