当前位置: 首页 > 知识库问答 >
问题:

无法使用kerberos票证使用java代码创建hadoop文件

白丁雨
2023-03-14

我们的hadoop集群使用kerberos,所以我们需要先使用kinit,然后使用类似“hadoop fs-ls/”的命令。现在我使用jaas和gssapi登录并在集群中创建文件,但失败了。这是我的代码:

import java.security.PrivilegedAction;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;  
import org.ietf.jgss.*;

public static void main(String[] args) throws LoginException
{
    System.setProperty("sun.security.krb5.debug", "false");
    System.setProperty("java.security.krb5.realm", "H236");
    System.setProperty("java.security.krb5.kdc", "172.16.0.236");
    System.setProperty( "javax.security.auth.useSubjectCredsOnly", "false");
    System.setProperty("java.security.auth.login.config",
            "/etc/hadoop/conf/jaas.conf");
           LoginContext lc = null;
           lc = new LoginContext("Client");
           lc.login();
           System.out.println("Authentication succeeded!");

       Subject subject = lc.getSubject();
       Subject.doAs( subject, new PrivilegedAction<byte[]>() 
           {
        public byte[] run() 
        {
            Configuration conf = new Configuration();

            try
            {
                Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
                GSSManager manager = GSSManager.getInstance();
                GSSName clientName = manager.createName("hdfs/172.16.0.239@H236", 
                        GSSName.NT_USER_NAME);
                GSSCredential clientCreds = manager.createCredential(clientName,
                        GSSCredential.DEFAULT_LIFETIME,
                        krb5Mechanism,
                        GSSCredential.INITIATE_ONLY);
                GSSName serverName = manager.createName("hdfs@172.16.0.239", 
                        GSSName.NT_HOSTBASED_SERVICE);
                GSSContext context = manager.createContext(serverName,
                        krb5Mechanism,
                                            clientCreds,
                                            GSSContext.DEFAULT_LIFETIME);
                context.requestMutualAuth(true);
                context.requestConf(false);
                context.requestInteg(true);
                System.out.println(clientCreds.getName().toString());
                System.out.println(clientCreds.getRemainingLifetime());                     

                    byte[] outToken = context.initSecContext(new byte[0], 0, 0);
                //create file on hadoop cluster
                FileSystem fs = FileSystem.get(conf);
                Path f = new Path("hdfs:///hdfs/123");
                FSDataOutputStream s = fs.create(f, true);
                System.out.println("done\n");                   
                                    int i = 0;
                for (i = 0; i < 100; ++i)
                    s.writeChars("test");
                s.close();

            }catch (Exception e)
                       {
                                    e.printStackTrace();
                       }
                            return null;
                  }//endof run
        });
   }//endof main

贾斯。具体如下:

Client {
          com.sun.security.auth.module.Krb5LoginModule required
          debug=true
          storeKey=true
          doNotPrompt=true
          useKeyTab=true
          keyTab="/etc/hadoop/conf/hdfs.keytab"
          principal="hdfs/172.16.0.239@H236";
         };

我的登录用户名是root,在使用“hadoop jar./client.jar”之前运行此代码,我运行kdestory删除kerberos缓存,然后我得到以下错误:

Authentication succeeded!
ERROR security.UserGroupInformation: PriviledgedActionException as:root (auth:KERBEROS) cause:javax.sec
urity.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided      
(Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))]
ipc.Client: Exception encountered while connecting to the server : javax.security.sasl.SaslExcepti
on: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Attempt to    
obtain new INITIATE credentials failed! (null))]
ERROR security.UserGroupInformation: PriviledgedActionException as:root (auth:KERBEROS) cause:java.io.I
OException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid   
credentials provided (Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))]
WARN retry.RetryInvocationHandler: Exception while invoking class org.apache.hadoop.hdfs.protocolPB.Cli
entNamenodeProtocolTranslatorPB.create. Not retrying because the invoked method is not idempotent,   
and unable to determine whether it was invoked
java.io.IOException: Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: 
GSSinitiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Attempt to 
obtain new INITIATE credentials failed! (null))]; Host Details : local host is: "XP236/172.16.0.236"; destination 
host is: "172.16.0.236":8020;at org.apache.hadoop.net.NetUtils.wrapException(NetUtils.java:760)

我不知道如何让它工作,有人能帮我吗,非常感谢。

共有1个答案

东方新霁
2023-03-14

请使用下面的代码通过代理用户代码访问安全的hadoop,在core-site中进行配置。xml也。。。类似于ooozie访问

import java.security.PrivilegedExceptionAction;
import java.text.SimpleDateFormat;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;

public class HdfsTest {

public static void main(String args[]) {
    final Configuration conf = new Configuration();
    try {

        conf.set("fs.defaultFS",
                "hdfs://ibm-r1-node7.ibmbi-nextgen.com:8020");
        UserGroupInformation.setConfiguration(conf);

        UserGroupInformation ugi = UserGroupInformation.createProxyUser(
                args[0],   UserGroupInformation.getUGIFromTicketCache(
                        "/tmp/krb5cc_0", args[1]));

        System.out.println("--------------status---:"
                + UserGroupInformation.isLoginKeytabBased());

        System.out.println("---------AFTER LOGIN-----:");

        ugi.doAs(new PrivilegedExceptionAction<Void>() {
            public Void run() throws Exception {

                FileSystem fs = FileSystem.get(conf);
                Path path = new Path("hdfs://10.132.100.224:8020/tmp/root");

                FileStatus[] statusArray = fs.listStatus(path);
                System.out.println("------------------------------"
                        + fs.listStatus(path));
                int count = 0;

                SimpleDateFormat sdf = null;
                for (FileStatus status : statusArray) {

                    Long blockSize = status.getBlockSize();

                    String permission = status.getPermission() + "";
                    int replication = status.getReplication();
                    String owner = status.getOwner();
                    String paths = status.getPath() + "";
                    boolean file = status.isFile();
                    Long length = status.getLen();
                    String group = status.getGroup();
                    System.out.println("BlockSize   :" + blockSize);
                    System.out.println("Group   :" + group);
                    System.out.println("Length  :" + length);
                    System.out.println("Owner   :" + owner);
                    System.out.println("Replication :" + replication);
                    System.out.println("File     :" + file);
                    System.out.println("Permission  :" + permission);
                    System.out.println("Path    :" + paths);
                    count++;
                    System.out
                            .println("-------------without auth-----count---------------"
                                    + count);
                }

                return null;
            }
        });

    } catch (Exception e) {
        System.out.println("--------EXCEPTION________________");
        e.printStackTrace();

    }
}

}

 类似资料:
  • 问题内容: 在我的服务器应用程序中,我正在从Java应用程序连接到受Kerberos保护的Hadoop群集。在应用程序启动时,我会打电话给 我正在使用本机API(例如和)进行基本的File操作 我的应用程序在24小时后引发以下错误。这就是Kerberos票证的到期日。 我的应用程序使用Java 8,并且遇到了此错误。 但是,看起来我的应用程序使用的hadoop- common-2.7.1.2.4.

  • 问题内容: 我正在使用spnego(http://spnego.sourceforge.net)在JBoss下进行kerberos身份验证。 我需要解密kerberos票证才能访问包含PAC数据的授权数据。需要PAC数据来决定要授予用户哪些角色。 如何访问和解密kerberos票?我在网上搜索了示例,但没有任何努力。 问题答案: 这些家伙具有完整的PAC解码实现: http://jaasloung

  • 我希望我能在这里说清楚: 让一个用户使用Kerberos向应用程序a进行身份验证(代码使用JAAS Krb5LoginModule) 客户机现在还需要向应用程序B进行身份验证 Kerberos票证仍然有效 如何确保应用程序B的身份验证流不会尝试创建新的Kerberos票证 当我使用JAAS时,我执行: (我当然向提供者凭据传递了一个回调处理程序,以及用作配置索引的名称,请参阅此处的javadoc)

  • 我已经编写了一个在Windows下运行的简单JavaHTTP客户端。客户端与需要通过SPNego进行Kerberos身份验证的Web服务器进行通信。 我遇到了两个问题: > 服务票证没有存储在我的凭据缓存中。执行请求后,我希望看到一个Kerberos服务票存储在我的凭据缓存下的

  • 我正在使用java创建一个zip文件,但我无法得到任何代码工作。我尝试了很多特定于Java7和Java8的方法,但所有的方法都显示出某种错误,是我的代码中有错误还是需要改进? 在这一行出现错误 请指导我:) 运行时出错:

  • 我有Kerberos并启用了Hadoop集群。我需要使用Java代码执行HDFS操作。 多谢了。