走过路过的java/hadoop大神,帮忙给看看。现在我的java程序,需要同时实现对多个集群的读写,这些集群分别由kerberos和simple这样不同的安全级别,我是在方法中用分支实现的,但是访问时,总是会出现互相影响的情况,基本有两种异常。
如果simple集群访问成功,kerberos集群会失败,异常信息:
org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]
如果kerberos集群访问成功,simple集群会失败,异常信息:
server asks to fall back to simple auth but this client is configured to only allow secure connections
我连接hdfs的java代码如下(其中的FileSystem对象fs返回后,在上下文使用来获取输入流和输出流):
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
// iskerberos为判断是否需要kerberos认证,uri指登陆的集群;因为是多线程运行,会有线程同时进入if和else分支
public FileSystem getHdfsStream(Boolean iskerberos, uri) {
Configuration conf = new Configuration();
if (iskerberos) {
System.setProperty("java.security.krb5.conf", "D:\\krb5.conf");
conf.set("hadoop.security.authentication", "kerberos");
conf.set("hadoop.security.authorization", true);
try {
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab(USER_KEY, KEY_TAB_PATH);
FileSystem fs = FileSystem.get(URI.create(uri), conf);
return fs;
} catch (IOException e) {
e.printStackTrace();
}
} else {
UserGroupInformation.setConfiguration(conf);
FileSystem fs = FileSystem.get(URI.create(uri), conf);
return fs;
}
return null;
}
我也试了将if和else中创建UserGroupInformation对象,在对象doAs方法下生成fs,详细代码如下:
// ugi是在类中定义的成员变量UserGroupInformation ugi= null
if (iskerberos) {
System.setProperty("java.security.krb5.conf", "D:\\krb5.conf");
conf.set("hadoop.security.authentication", "kerberos");
conf.set("hadoop.security.authorization", true);
try {
ugi.setConfiguration(conf);
ugi.loginUserFromKeytab(USER_KEY, KEY_TAB_PATH);
FileSystem fs = ugi.doAs(new PrivilegedExceptionAction <FileSystem>) {
public FileSystem run() thows IOException{
return FileSystem.get(URI.create(uri), conf);
}
});
return fs;
} catch (IOException e) {
e.printStackTrace();
}
} else {
ugi.setConfiguration(conf);
ugi.createRemoteUser(USER_KEY);
FileSystem fs = ugi.doAs(new PrivilegedExceptionAction <FileSystem>) {
public FileSystem run() thows IOException{
return FileSystem.get(URI.create(uri), conf);
}
});
return fs;
}
但是结果依然不行。。。
最近被这个问题困扰了很久,一直没找到解决办法。还烦请给指点一二!
解决方案补充:
设置conf为允许simple模式通过kerberos链接:
import org.apache.hadoop.fs.CommonConfigurationKeys
conf.setBoolean(CommonConfigurationKeys.IPC_CLIENT_FALLBACK_TO_SIMPLE_AUTH_ALLOWED_KEY, true)
可解决Hbase、HDFS、Hive开启和不开启kerberos同时抽取的问题,kafka还存在问题,暂时找不到解决办法。