java能否实现访问kerberos和simple安全级别的两个集群(补充解决方案)

走过路过的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还存在问题,暂时找不到解决办法。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
要在 Java实现 Elasticsearch + Kerberos 认证,可以按照以下步骤进行操作: 1. 配置 Kerberos:在使用 Kerberos 认证之前,您需要配置 Kerberos 客户端并在 Elasticsearch 集群中启用 Kerberos 认证。这通常需要与管理员一起完成,并且可能涉及到修改 Kerberos 相关的配置文件和添加 Kerberos 群组用户等操作。 2. 配置 JAAS 文件:在 Java 应用程序中实现 Kerberos 认证需要使用 JAAS(Java Authentication and Authorization Service)。您需要在应用程序中配置 JAAS 文件来告诉 Java 如何使用 Kerberos 进行身份验证。您可以创建一个名为“krb5.conf”的文件来指定 Kerberos 服务器的位置和其他相关信息,然后在 JAAS 文件中引用此文件。 3. 配置 Elasticsearch 客户端:在 Java 应用程序中连接 Elasticsearch 时,您需要指定 Elasticsearch 客户端的 Kerberos 配置。您可以在 Elasticsearch 客户端中使用 TransportClient 或者 RestClient,具体使用哪种方式需要根据您的需求来确定。对于 TransportClient,您可以使用`org.elasticsearch.xpack.security.authc.support`包中的`KerberosHeader`类来指定 Kerberos 配置;对于 RestClient,您可以使用`org.apache.http.impl.auth`包中的`SPNegoSchemeFactory`类来指定 Kerberos 配置。 4. 编写 Java 代码:最后,在 Java 应用程序中编写代码来连接 Elasticsearch 集群并进行身份验证。您需要使用 JAAS 文件中指定的 Kerberos 凭据来创建一个 Krb5LoginModule,并将其添加到您的应用程序中。然后,使用 Elasticsearch 客户端连接 Elasticsearch 集群,并在请求中添加 Kerberos 认证头信息。例如: ```java Krb5LoginModule krb5 = new Krb5LoginModule(); krb5.initialize(new Subject(), null, new HashMap<>(), new HashMap<>()); krb5.login(); TransportClient client = new PreBuiltTransportClient(Settings.EMPTY) .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300)); client.addHeaders(new KerberosHeader(krb5.getTicket())); ``` 以上是基本的步骤,具体实现需要根据您的环境和需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值