HDFS调用listStatus报AccessControlException:客户端无法通过TOKEN/KERBEROS认证
HDFS Kerberos认证报错排查
问题背景
我尝试在Data Node上运行应用,从Name Node列出文件,使用的HDFS配置代码如下:
Configuration config = new Configuration(); System.setProperty("java.security.krb5.conf", "/etc/krb5.conf"); config.addResource(new Path("/etc/hadoop/conf/core-site.xml")); config.addResource(new Path("/etc/hadoop/conf/hdfs-site.xml")); config.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem"); config.set("fs.file.impl", "org.apache.hadoop.fs.LocalFileSystem"); config.set("hadoop.security.authentication", "kerberos"); UserGroupInformation.setConfiguration(config); UserGroupInformation.loginUserFromKeytab("kt_user@QA.DF.SBRF.COM", "kt_user.keytab"); UserGroupInformation user = UserGroupInformation.getLoginUser(); System.out.println("SU " + user.toString()); System.out.println("Current userName: " + UserGroupInformation.getCurrentUser().getUserName()); hdfs = FileSystem.get(config);
另外还设置了系统属性:
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
当前验证状态
- FileSystem实例创建成功
- 输出的
SU内容:kt_user@QA.DF.SBRF.COM (auth KERBEROS) - 输出的
Current userName:内容:kt_user@QA.DF.SBRF.COM - 已通过
klist命令验证principal正确,keytab文件与jar包位于同一目录/home/user
报错信息
调用hdfs.listStatus(new Path("some real path"))时返回:
org.apache.hadoop.security.AccessControlException: Client cannot authenticate via:[TOKEN, KERBEROS]
开启Kerberos调试后发现核心错误:
error Message is Additional pre-authentication required
解决方向
1. 重新生成包含预认证密钥的keytab
"Additional pre-authentication required"说明KDC要求该principal必须进行预认证,但当前keytab未包含对应密钥:
- 登录KDC服务器,执行命令查看principal属性:
若输出包含kadmin.local -q "getprinc kt_user@QA.DF.SBRF.COM"requires_preauth,则重新生成keytab:
将新生成的keytab替换到应用目录kadmin.local -q "ktadd -k kt_user.keytab kt_user@QA.DF.SBRF.COM"/home/user。
2. 校验krb5.conf配置
确保/etc/krb5.conf中配置正确:
default_realm设置为QA.DF.SBRF.COMrealms块中指定正确的KDC和admin_server地址- 注意Kerberos realm名称必须为大写,避免大小写不匹配
3. 调整Hadoop认证配置
在代码的Configuration中添加以下配置,强制优先使用Kerberos认证:
config.set("dfs.namenode.kerberos.principal", "hdfs/_HOST@QA.DF.SBRF.COM"); // 替换为你的NameNode实际principal config.set("dfs.client.use.datanode.hostname", "true"); // 若DataNode使用主机名而非IP通信,需开启此配置
4. 测试keytab有效性
在应用目录执行命令验证keytab是否能正常获取票据:
kinit -kt kt_user.keytab kt_user@QA.DF.SBRF.COM
执行klist查看票据,若成功获取则keytab有效;若仍报预认证错误,回到步骤1重新生成。
5. 移除干扰性系统属性
尝试删除System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");,该属性可能干扰Hadoop默认的Kerberos认证流程。
内容的提问来源于stack exchange,提问作者Jelly
相关产品推荐
相关产品推荐

