java如何通過Kerberos認(rèn)證方式連接hive
在數(shù)據(jù)源管理功能中,需要適配mysql、postgresql、hive等數(shù)據(jù)源。
mysql和postgresql連接方式一致,只需要驅(qū)動(dòng)和jdbcurl即可,而hive背后是大數(shù)據(jù)集群,多采用Kerberos的方式保護(hù)集群環(huán)境,要想與大數(shù)據(jù)集群正常交互,需要經(jīng)過kdc認(rèn)證獲取ticket,因此獲取hive連接前需要先通過Kerberos認(rèn)證
Java實(shí)現(xiàn)Kerberos認(rèn)證
主要方法
# 從keytab文件中加載用戶標(biāo)識(shí)并登錄 org.apache.hadoop.security.UserGroupInformation#loginUserFromKeytab
依賴
kerberos相關(guān)配置文件:krb5.conf、keytab文件從大數(shù)據(jù)集群管理員那獲取
依賴:hive-jdbc:3.1.3(hive安裝目錄中帶有該驅(qū)動(dòng)包,可查看使用的版本)、hadoop-common:3.3.6,版本需和hive服務(wù)版本一致,在springboot3的框架下需要排除以下依賴,否則啟動(dòng)報(bào)錯(cuò)
<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認(rèn)證失敗");
}除了上述方式外,也可采用JAAS可插拔的認(rèn)證模塊進(jìn)行Kerberos認(rèn)證
續(xù)期
Kerberos的ticket存在有效期,過期后導(dǎo)致服務(wù)不可用
Kerberos ticket存在兩種有效期,ticket timelife(票據(jù)生命周期)、renewable lifetime(可再生周期)
- ticket的時(shí)間超過ticket lifetime時(shí),該ticket將不可用
- 在renewable lifetime的時(shí)間內(nèi),可以對(duì)即將過期的ticket進(jìn)行續(xù)期,超過renewable lifetime時(shí)間后,無法續(xù)期
- 例如kerb5.conf文件中的配置:ticket_lifetime = 24h renewable_lifetime = 7d,則在登錄后的24小時(shí)內(nèi),可以對(duì)即將過期的ticket進(jìn)行續(xù)期,距第一次登錄7天后,將不再允許續(xù)期
UserGroupInformation提供了認(rèn)證續(xù)期的私有方法UserGroupInformation#reloginFromKeytab(boolean),該方法有兩個(gè)觸發(fā)入口UserGroupInformation#checkTGTAndReloginFromKeytab和UserGroupInformation#reloginFromKeytab()


值得注意的是
UserGroupInformation#loginUserFromKeytab
方法中會(huì)開啟異步任務(wù),定時(shí)觸發(fā)續(xù)期方法,觸發(fā)的續(xù)期方法即是
UserGroupInformation#reloginFromKeytab()


向線程池中提交續(xù)期的任務(wù)


也可以自定義觸發(fā)續(xù)期的邏輯, 定期觸發(fā)
UserGroupInformation.getLoginUser().checkTGTAndReloginFromKeytab()
連接hive
Kerberos認(rèn)證之后,使用hive-jdbc連接hive,之后與連接mysql、pg的方式無異,使用DriverManager或數(shù)據(jù)源連接池Hikari皆可
遇到的問題
一開始選擇hadoop-common的版本是3.1.3,執(zhí)行Kerberos認(rèn)證時(shí)報(bào)錯(cuò)

KerberosUtil無法訪問sun.security.krb5.Config(它在java.security.jgss模塊中)。
分析
本項(xiàng)目采用的框架是spring boot3版本,最低要求的jdk版本是17,而Java在9之后引入了模塊化機(jī)制,模塊必須顯式聲明他們要到導(dǎo)出的包以供其他模塊使用。
但是java.security.jgss模塊的module-info.class文件中并未聲明

解決方式
1.在JVM的啟動(dòng)參數(shù)上增加以下參數(shù)
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
2.升級(jí)hadoop-common版本到3.3.6
在該版本中KerberosUtil并未通過反射訪問sun.security.krb5.Config
hadoop-common:3.1.3版本的KerberosUtil

hadoop-common:3.3.6版本的KerberosUtil

擴(kuò)展
利用JAAS機(jī)制認(rèn)證Kerberos,不再使用UserGroupInformation進(jìn)行認(rèn)證
增加一個(gè)配置文件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);
}思考
有時(shí)我們開發(fā)的系統(tǒng)是要部署到客戶現(xiàn)場使用,而客戶現(xiàn)場使用的hive版本和司內(nèi)環(huán)境使用的版本可能不同。一般在程序開發(fā)時(shí)使用的依賴版本皆是定義在pom文件中,一旦打包之后依賴的版本就是固定的。因此需要考慮程序可適配不同的hive-jdbc版本,能夠動(dòng)態(tài)加載不同版本的hive-jdbc,或者在項(xiàng)目啟動(dòng)時(shí)可以指定額外的hive-jdbc驅(qū)動(dòng)包
- 使用類加載器在程序運(yùn)行時(shí)動(dòng)態(tài)從指定路徑讀取并加載指定的驅(qū)動(dòng)jar包
URLClassLoader loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader()); Class.forName(driverName, true, loader);
- 在項(xiàng)目啟動(dòng)時(shí)能夠?qū)⒅付ǖ哪夸浿械膉ar包放到類路徑中
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
本文給大家分享的是一則使用java編寫的文件管理器的代碼,新人練手的作品,邏輯上還是有點(diǎn)小問題,大家?guī)兔纯窗伞?/div> 2015-04-04
java實(shí)現(xiàn)壓縮字符串和java字符串過濾
這篇文章主要介紹了java實(shí)現(xiàn)壓縮字符串和java字符串過濾,需要的朋友可以參考下2014-04-04
SpringBoot整合Minio的過程(支持公有及私有bucket)
Bucket 是存儲(chǔ)Object的邏輯空間,每個(gè)Bucket之間的數(shù)據(jù)是相互隔離的,對(duì)用戶而言,相當(dāng)于存放文件的頂層文件夾,這篇文章主要介紹了SpringBoot整合Minio的過程(支持公有及私有bucket),需要的朋友可以參考下2025-03-03
java如何調(diào)用kettle設(shè)置變量和參數(shù)
文章簡要介紹了如何在Java中調(diào)用Kettle,并重點(diǎn)討論了變量和參數(shù)的區(qū)別,以及在Java代碼中如何正確設(shè)置和使用這些變量,避免覆蓋Kettle中已設(shè)置的變量,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)大家參考和使用腳本之家2025-01-01
SpringBoot項(xiàng)目設(shè)置斷點(diǎn)debug調(diào)試無效忽略web.xml問題的解決
這篇文章主要介紹了SpringBoot項(xiàng)目設(shè)置斷點(diǎn)debug調(diào)試無效忽略web.xml問題的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Spring?Security+JWT如何實(shí)現(xiàn)前后端分離權(quán)限控制
本篇將手把手教你用?Spring?Security?+?JWT?搭建一套完整的登錄認(rèn)證與權(quán)限控制體系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04最新評(píng)論

