最近,公司生产集群添加kerberos安全认证后,访问集群的任何组件都需要进行认证,这样问题来了,对于impala,未配置kerberos安全认证之前通过impala的jdbc驱动(impala-jdbc),配置连接字符串

jdbc:impala://192.168.1.10:21050/default;AuthMech=3;UID=user;PWD=pwd;UseSasl=0

是可以正常访问的,但是开启了kerberos后,impala访问报错,经过阅读impala jdbc使用文档(https://www.cloudera.com/documentation/other/connectors/impala-jdbc/2-5-5/Cloudera-JDBC-Driver-for-Impala-Install-Guide-2-5-5.pdf),可以发现,对于启用kerberos的impala连接字符串需要调整为如下:

jdbc:impala://192.168.1.10:21050/default;AuthMech=1;KrbHostFQDN=hostalias;KrbServiceName=impala

其中:KrbHostFQDN需要指定连接哪台服务器的impalad,需要使用服务器的别名。

调整jdbc配置,连接impala失败,异常信息如下

java.sql.SQLException: [Simba][ImpalaJDBCDriver](500168) Error creating login context using ticket cache: Unable to obtain Principal Name for authentication .
......
Caused by: com.cloudera.support.exceptions.GeneralException: [Simba][ImpalaJDBCDriver](500168) Error creating login context using ticket cache: Unable to obtain Principal Name for authentication .
... 39 more
Caused by: javax.security.auth.login.LoginException: Unable to obtain Principal Name for authentication
at com.sun.security.auth.module.Krb5LoginModule.promptForName(Krb5LoginModule.java:841)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:704)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:617)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
at com.cloudera.jdbc.kerberos.Kerberos.getSubjectViaTicketCache(Unknown Source)
at com.cloudera.hivecommon.api.HiveServer2ClientFactory.createTransport(Unknown Source)
at com.cloudera.hivecommon.api.HiveServer2ClientFactory.createClient(Unknown Source)
at com.cloudera.hivecommon.core.HiveJDBCCommonConnection.connect(Unknown Source)
at com.cloudera.impala.core.ImpalaJDBCConnection.connect(Unknown Source)
at com.cloudera.jdbc.common.BaseConnectionFactory.doConnect(Unknown Source)
at com.cloudera.jdbc.common.AbstractDriver.connect(Unknown Source)
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1421)
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1477)
at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:677)

  通过上述异常信息可知,kerberos认证未通过。由于是window环境,不属于hadoop安全范围,所以认证失败,为了认证通过,需要如下的代码:

@Test
/**
* 连接Impala查询
*/
public void testImpala() throws SQLException, IOException {
Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "Kerberos");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab(user, keyTabPath);
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
String query = "select * from table limit 1";
loginUser.doAs((PrivilegedAction<Void>) () -> {
try {
try (Connection connection = DriverManager.getConnection(impalaUrl)) {
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery(query);
while (resultSet.next()) {
System.out.println(resultSet.getObject(1));
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
});
}

 

首先,设置hadoop.security.authentication为kerberos,其次,使用UserGroupInformation来进行操作。这样虽然kerberos认证是通过了,但是还是有其他异常:

java.lang.IllegalArgumentException: Can't get Kerberos realm
....
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.security.authentication.util.KerberosUtil.getDefaultRealm(KerberosUtil.java:84)
at org.apache.hadoop.security.HadoopKerberosName.setConfiguration(HadoopKerberosName.java:63)
... 30 more
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.Config.getDefaultRealm(Config.java:1029)
... 36 more

  无法获取Kerberos realm,具体出现这个问题的地方在sun.security.krb5.Config文件中,阅读该Config类的构造函数,会发现如下代码:

Config(){
.....
try {
String var3 = this.getJavaFileName();
List var2;
if(var3 != null) {
var2 = this.loadConfigFile(var3);
this.stanzaTable = this.parseStanzaTable(var2);
if(DEBUG) {
System.out.println("Loaded from Java config");
}
} else {
boolean var4 = false;
if(isMacosLionOrBetter()) {
try {
this.stanzaTable = SCDynamicStoreConfig.getConfig();
if(DEBUG) {
System.out.println("Loaded from SCDynamicStoreConfig");
} var4 = true;
} catch (IOException var6) {
;
}
} if(!var4) {
var3 = this.getNativeFileName();
var2 = this.loadConfigFile(var3);
this.stanzaTable = this.parseStanzaTable(var2);
if(DEBUG) {
System.out.println("Loaded from native config");
}
}
}
} catch (IOException var7) {
;
}
} private String getJavaFileName() {
String var1 = getProperty("java.security.krb5.conf");
if(var1 == null) {
var1 = getProperty("java.home") + File.separator + "lib" + File.separator + "security" + File.separator + "krb5.conf";
if(!this.fileExists(var1)) {
var1 = null;
}
} if(DEBUG) {
System.out.println("Java config name: " + var1);
} return var1;
} private String getNativeFileName() {
String var1 = null;
String var2 = getProperty("os.name");
if(var2.startsWith("Windows")) {
try {
Credentials.ensureLoaded();
} catch (Exception var4) {
;
} if(Credentials.alreadyLoaded) {
String var3 = getWindowsDirectory(false);
if(var3 != null) {
if(var3.endsWith("\\")) {
var3 = var3 + "krb5.ini";
} else {
var3 = var3 + "\\krb5.ini";
} if(this.fileExists(var3)) {
var1 = var3;
}
} if(var1 == null) {
var3 = getWindowsDirectory(true);
if(var3 != null) {
if(var3.endsWith("\\")) {
var3 = var3 + "krb5.ini";
} else {
var3 = var3 + "\\krb5.ini";
} var1 = var3;
}
}
} if(var1 == null) {
var1 = "c:\\winnt\\krb5.ini";
}
} else if(var2.startsWith("SunOS")) {
var1 = "/etc/krb5/krb5.conf";
} else if(var2.contains("OS X")) {
var1 = this.findMacosConfigFile();
} else {
var1 = "/etc/krb5.conf";
} if(DEBUG) {
System.out.println("Native config name: " + var1);
} return var1;
}

  其中重要的就是getJavaFileName和getNativeFileName两个方法,getJavaFileName中会查找java.security.krb5.conf属性,而getNativeFileName会查找系统目录(对于window就是C:\Windows目录)。

所以,在window环境下,可以在系统属性中配置上java.security.krb5.conf属性来指定krb5.ini文件,或将krb5.conf 保存到%JAVA_HOME%\lib\security\目录下,或将krb5.ini文件保存到c:\window目录下即可正常访问kerberos安全认证的Impala。

  程序调试kerberos异常信息,启动的时候设置“-Dsun.security.krb5.debug=true” ,再次启动就会输出kerberos的详细信息,根据详细信息进行排查。 

 截图的异常信息是开启了kerberos的调试信息后打印的信息。其中“Clock skew too great”说明系统时间与kerberos系统的时间差距超出了5分钟。

测试环境:

客户端操作系统: window 7

JDK:1.8

Impala-jdbc:

 <dependency>
<groupId>com.cloudera.impala</groupId>
<artifactId>impala-jdbc</artifactId>
<version>2.5.34-cdh5.7.2</version>
</dependency>

服务器环境:

操作系统:Centos 6.5

CDH:5.7.2

window 环境下jdbc访问启用kerberos的impala的更多相关文章

  1. window环境下将solr6.3部署到tomcat中

    1.我下载的solr是6.3版本的,需要jdk1.8及以上,tomcat8 JDK1.8的下载地址:http://www.Oracle.com/technetwork/Java/javase/down ...

  2. window环境下glog的安装

    window环境下glog的安装 分类: c++2014-09-23 14:12 32人阅读 评论(0) 收藏 举报 下载后解压,利用Visual Studio打开google-glog.sln.生成 ...

  3. Window环境下配置MySQL 5.6的主从复制

    原文:Window环境下配置MySQL 5.6的主从复制 1.环境准备 Windows 7 64位 MySQL 5.6 主库:192.168.103.207 从库:192.168.103.208 2. ...

  4. 【转】mysql8.0 在window环境下的部署与配置

    [转]mysql8.0 在window环境下的部署与配置 今天在阿里云window服务器上配置mysql环境,踩了一些坑,分享出来.需要的朋友可以看看.额,或许有人要吐槽我为什么不在linux上去配置 ...

  5. window环境下杀死tomcat

    window环境下杀死进程 1.首先查找到占用8080端口的进程号PID是多少(tomcat默认是8080端口,假如你修改了tomcat的监听端口,请输入你的tomcat端口号) netstat -a ...

  6. window环境下npm install node-sass报错

    最近准备想用vue-cli初始化一个项目,需要sass-loader编译: 发现window下npm install node-sass和sass-loader一直报错, window 命令行中提示我 ...

  7. JAVA中调用LevelDB用于Linux和Window环境下快速存储KV结构

    一.简介 JAVA中调用LevelDB用于Linux和Window环境下快速存储KV结构 二.依赖 <!-- https://mvnrepository.com/artifact/org.fus ...

  8. Window环境下,PHP调用Python脚本

    参考 php调用python脚本*** php 调用 python脚本的方法 解决办法:php提供了许多调用其他脚本或程序的方法,比如exec/system/popen/proc_open/passt ...

  9. nodejs 修改端口号 process.env.PORT(window环境下)

    各个环境下,nodejs设置process.env.PORT的值的命令,如下1.linux环境下: PORT= node app.js 使用上面命令每次都需要重新设置,如果想设置一次永久生效,使用下面 ...

随机推荐

  1. ListView多种item注意以及自己出现的莫名其妙的错误

    如果ListView不懂,请绕路 1.ListView添加多个item必须用到的两个方法 getViewTypeCount一共有多少种item,我这里写的两种 getItemViewType当前pos ...

  2. beginAppearanceTransition

    - (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated __OSX_AVAILABLE_STARTING ...

  3. spring boot 自定义过滤器链

    spring boot 会按照order值的大小,从大到小的顺序来依次过滤. 贴下代码: package com.osp.ucenter; import org.springframework.boo ...

  4. 复习一下property

    在面向对象程序里,一个对象不要直接访问另一个对象内部的数据.所以我们使用accessor methods来进行对象内部的数据交互. accessor methods(getters and sette ...

  5. iOS 常用小功能 总结

    常用小功能 iOS中的很多小功能都是非常简单的,几行代码就搞定了,比如打电话.打开网址.发邮件.发短信等 打电话 方法一(不被采用): 拨号之前会弹框询问用户是否拨号,拨完后能自动回到原应用 NSUR ...

  6. matlab 怎么建立结构体数组?

    https://zhidao.baidu.com/question/537198107.html 怎么定义一个结构体数组,使数组的每个元素是一个结构体变量.像这样:a=(1,2)a(1)=struct ...

  7. python爬虫对于gb2312

    对于刚刚接触python爬虫的人,常常会碰到一个比较烦的问题, 如果网页是GB2312编码格式,我们直接decode(’GB2312‘)一般python都会报错: GB2312不能编码该页面. 这就比 ...

  8. linux常用命令:date 命令

    在linux环境中,不管是编程还是其他维护,时间是必不可少的,也经常会用到时间的运算,熟练运用date命令来表示自己想要表示的时间,肯定可以给自己的工作带来诸多方便. 1.命令格式: date [参数 ...

  9. Linux基础命令---gzexe

    gzexe 压缩可执行文件,在执行程序的时候可以自动实现解压.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法       g ...

  10. Shell脚本实现检测某ip网络畅通情况,实战用例

    Shell脚本实现检测某ip网络畅通情况,实战用例 环境准备,linux shell 发送email 邮件:1.安装sendmailyum -y install sendmail安装好sendmail ...