欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java通过认证kerberos连接HDFS

程序员文章站 2022-03-24 11:37:01
...

针对java语言中通过kerberos认证访问hadoop环境可以利用第三方api包。UserGroupInformation这个类JAAS 框架上封装了Hadoop 的用户信息,更确切地说是subject做了一层封装:

    UserGroupInformation(Subject subject) {
    this.subject = subject;
    this.user = subject.getPrincipals(User.class).iterator().next();
    this.isKeytab = !subject.getPrivateCredentials(KerberosKey.class).isEmpty();
    this.isKrbTkt = !subject.getPrivateCredentials(KerberosTicket.class).isEmpty();
  }

JAAS 是 Java 认证和授权服务(Java Authentication and Authorization Service)的缩写, 主要包含以下几个实体:
(1) Subject
Subject 是一个不可继承的实体类,它标志一个请求的来源, 包含相关的凭证标识(Principal) 和 公开和私有的凭据。
(2) Principal
凭证标识,认证成功后,一个 Subject 可以被关联多个Principal。
(3) Credential

凭据,有公有凭据以及私有凭据。


在安全模式下,UGI 支持不同LoginContext 配置,均是通过 HadoopConfiguration 类动态产生:
(1) hadoop-user-kerberos:
使用kerberos缓存凭证登陆的配置,useTicketCache设置为 true。
(2) hadoop-keytab-kerberos:

使用keytab登陆的配置,useKeyTab 置为 true。


针对以上两种配置,分别对应下面两种方案:
方案一:
getLoginUser 方法使用的是hadoop-user-kerberos 配置认证:
A. 通过配置生成 LoginContext
B. 调用 LoginContext.login 方法完成登陆, 通过 ticket cache 中凭证完成登陆
C. 判断是否需要其他用户身份(proxy user)执行
D. 将 HADOOP_TOKEN_FILE_LOCATION 中的 token 加入 Credentials 集合当中
E. 另起一个线程做周期性的凭证更新 spawnAutoRenewalThreadForUserCreds

方案二:
loginUserFromKeytab 方法使用 hadoop-kerberos 配置认证:
A. 通过配置生成 LoginContext
B. 调用 LoginContext.login 方法完成登陆, 使用keytab完成登陆

从以上两种方案中可以看出,当我们存在凭证后并不需要主动做周期性地凭证更新,但是配置相对较繁琐。而方案二在访问集群执行相关操作前, 可以调用 checkTGTAndReloginFromKeytab 来尝试更新凭证,并且在凭证过期时,创建 IPC 失败会触发调用 reloginFromKeytab 来重新登陆。由此可见方案二较优,通过keytab文件以及principal调用loginUserFromKeytab方法进行hadoop的kerberos认证。

具体代码实现:

	config.addResource(new Path(coreSite));
	config.addResource(new Path(hdfsSite));
	UserGroupInformation.setConfiguration(config);
	UserGroupInformation.loginUserFromKeytab(principal, keytab);
	fs = FileSystem.get(config);

其中coreSite为core-site.xml文件路径;hdfsSite为hdfs-site.xml文件路径;principal为凭证标示;keytab为keytab文件路径。

正常情况下这样就可以通过认证了,但如果客户端不是在hadoop集群内运行的,

那么我们需要配置kerberos实例,

有两种办法可以设置:

1、在代码中添加这一行:

System.setProperty("java.security.krb5.conf", "krb5.conf");

2、如果不想改代码,则可以在执行客户端的指令上加上环境变量配置:

-Djava.security.krb5.conf=krb5.conf