更新时间:2018/11/9 11:35:53

更新内容:

1. 将

以下正文:

最近做一个项目涉及到读取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 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

*@author lshua

*@date 2018年5月4日

*/

public static Map getProperties(String confPath) {

log.info("-----loadConfig()... begin-----");

log.info("-----confPath = {}", confPath);

Map proMap = new HashMap(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> propSet = prop.entrySet();

for(Entry 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

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐