hadoop kerberos认证

  更新时间:2018/11/9 11:35:53
  更新内容:
    1. 将 判断文件的可读权限判断文件类型分别单独出一个文章;
    2. 判断文件的可读权限做了api的扩展和代码优化,提供所有权限的判断。

  以下正文:
  最近做一个项目涉及到读取hdfs数据时要进行kerberos认证,上网找了挺多例子试了挺久才成功,项目完成了这里记录一下。因为时间过去挺久忘了当初是参考哪个博文验证成功的了,虽无法指明但表示感谢!

kerberos认证

  这里是用keytab和krb5.conf文件进行kerberos认证,至于这两个文件是干嘛的自行搜索(其实我也不太清除o.o,就是用来验证Kerberos的了)。需要的相关信息配置在hdfs_info.properties文件中,配置如下:

## namenode的地址,hdfs://ip:port
hdfs_address=
## .keytab文件路径
key_tab_path=
## krb5.conf文件路径
krb5_path=
## hdfs-site.xml文件路径
hdfs_site_path=
## kerberos认证用户
login_user=

  这里我只是列出了需要配置的内容,相关信息配置成自己集群环境的信息就好,hdfs-site.xml中主要是需要dfs.namenode.kerberos.principal和dfs.datanode.kerberos.principa这两个配置信息,如果不想将整个配置文件导入(里面配置了很多信息)也可以直接conf里面设置即可:

// ""中填写对应配置的值
conf.set("dfs.namenode.kerberos.principal","");
conf.set("dfs.datanode.kerberos.principal","");

  然后Kerberos认证的类HdfsUtil.class中进行认证的方法kerberosCertify(),我将返回值由原来的void改为了Configuraiton,是想到kerberos认证是有过期时间的,不知道conf存储了认证信息,过期后是否需要重新认证,如果需要重新认证这样会方便写,且加个定时器定时去定时认证会更好,避免手动调用。如果不会过期那就还是void好点,且Configuration最好做单例处理,此处待确认和优化,具体代码如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cdc.common.util.PropertiesUtil;
import com.cdc.hdfs.enums.FilePermissionEnum;
import com.cdc.hdfs.enums.FileTypeEnum;


/**
 *@author lshua
 *@time 2018年6月27日
 *@description: 集群工具类 
 */

public class HDFSUtil {

    private static final Logger log = LoggerFactory.getLogger(HDFSUtil.class);
    /**
     * hdfs信息配置文件路径 resources目录下
     */
    private static final String HDFS_INFO_ADDRESS = "hdfs_info.properties";
    /**
     * hdfs配置信息
     */
    private static Map<String, String> proMap = PropertiesUtil.getProperties(HDFS_INFO_ADDRESS);
    /**
     * HDFS namenode地址
     */
    private static final String HDFS_ADDRESS = proMap.get("hdfs_address");
    /**
     * 认证需要的.keytab文件的路径
     */
    private static final String KEY_TAB_PATH = proMap.get("key_tab_path");
    /**
     * 配置文件krb5.conf的路径
     */
    private static final String KRB5_PATH = proMap.get("krb5_path");
    /**
     * hdfs-site.xml文件的路径
     */
    private static final String HDFS_SITE_PATH = proMap.get("hdfs_site_path");
    /**
     * kerberos认证用户名
     */
    private static final String LOGIN_USER = proMap.get("login_user");
    /**
     * 配置信息
     */
    private static Configuration conf = null;


/**
 * 对集群进行认证操作
 *
 *@return Configuration 返回包含认证信息的,失败返回null
 *@date 2018年11月2日
 */
public static Configuration kerberosCertify() {
    conf = new Configuration();
    // 设置kerberos配置信息
    System.setProperty("java.security.krb5.conf", KRB5_PATH);
    
    conf.set("fs.defaultFS", HDFS_ADDRESS);
    conf.set("fs.hdfs.impl", DistributedFileSystem.class.getName());  
    conf.set("fs.file.impl", LocalFileSystem.class.getName());  
    
    /**
     * 启用kerberos认证
     */
    conf.setBoolean("hadoop.security.authentication", true);
    conf.set("hadoop.security.authentication", "kerberos");  
    // 添加hdfs-site.xml的内容
    conf.addResource(new Path(HDFS_SITE_PATH));
    
    UserGroupInformation.setConfiguration(conf);
    try {
        // kerberos认证
        UserGroupInformation.loginUserFromKeytab(LOGIN_USER, KEY_TAB_PATH);
        UserGroupInformation.getLoginUser();
    } catch (Exception e) {
        log.error("------------hdfs kerberos 认证异常!--------------");
        e.printStackTrace();
        return null;
    }
    return conf;
} 

  代码中用到了一个自己写的PropertiesUtil.class工具类代码如下 :

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 *@author lshua
 *@time 2018年4月24日
 *@description: 配置文件的工具类
 */

public class PropertiesUtil {

    private static Logger log = LoggerFactory.getLogger(PropertiesUtil.class);

    /**
     *@description 根据文件路径获取配置信息
     *@param confPath 配置文件路径
     *@return Map<String, String>
     *@author lshua
     *@date 2018年5月4日
     */
    public static Map<String, String> getProperties(String confPath) {
        
        log.info("-----loadConfig()... begin-----");
        log.info("-----confPath = {}", confPath);
        
        Map<String, String> proMap = new HashMap<String, String>(32);
        
        Properties prop = new Properties();
        
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            fis = new FileInputStream(new File(confPath));
            bis = new BufferedInputStream(fis);
            prop.load(bis);
            
            Set<Entry<Object, Object>> propSet = prop.entrySet();
            
            for(Entry<Object, Object> entry : propSet) {
                proMap.put(entry.getKey().toString(), entry.getValue().toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("-----loadConf() error-----");
        } finally {
            try {
                if(bis != null) {
                    bis.close(); bis = null;
                }
                if(fis != null) {
                    fis.close(); fis = null;
                }
            } catch (Exception e) {
                log.info("------ close io stream error ! -----");
                e.printStackTrace();
            }
        }
        log.info("-----loadConfig()... end-----");
        
        return proMap;
    }
}

   需要注意的是因为开启的kerberos认证,所以当其他地方需要做hdfs的相关操作的时候不能直接new 一个Configuration出来,需要使用这里进行了kerberos验证包含验证信息的Configuration,所以开发一个接口给其他代码获取就好:

 /**
 * 获取进行了kerberos认证的configuration
 *
 *@return Configuration
 *@author lshua
 *@date 2018年7月27日
 */
public static Configuration getConfiguration() {
    return conf;
}

  代码在项目中已经验证通过了的,这里就不贴测试的代码了。配置正常应该是能正常使用的,最后附上相关的jar包gradle依赖:

// hadoop相关依赖,编译时需要。
compileOnly('org.apache.hadoop:hadoop-common:2.6.0') 
compileOnly('org.apache.hadoop:hadoop-hdfs:2.6.0')

// 日志
compile 'org.slf4j:slf4j-api:1.7.12'
compile 'log4j:log4j:1.2.17'

  emmmmmm有时候还要环境数据,大概说一下:

* jdk 1.7  
* eclipse 4.7.2  
* gradle 4.4.10  
* CDH5.8.3-hadoop2.6.0    
    原文作者:别情书
    原文地址: https://www.jianshu.com/p/ae273f6415b3
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞