最近,公司生产集群添加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. 几种outofmemory

    几种outofmemory的解决方法:1.  java.lang.OutOfMemoryError: PermGen space PermGen space的全称是Permanent Generati ...

  2. 为什么说Java语言是平台无关的?

    适当的整理了一下: 一.平台与机器指令 无论哪种编程语言编写的应用程序都需要经过操作系统和处理器来完成程序的运行,因此这里的平台是又OS和CPU所构成的,所谓的平台无关就是指软件的运行不会因操作系统. ...

  3. 64位win10+cuda8.0+vs2013+cuDNN V5下Caffe的编译安装教程并配置matlab2014a 接口

    一.需要安装的软件 1)vs2013,我是在http://www.52pojie.cn/thread-492326-1-1.html这个网址安装的.我之前用的是vs2012,按照网上的配置教程会爆各种 ...

  4. SQL 1

    SQL 教程 SQL 是用于访问和处理数据库的标准的计算机语言. 在本教程中,您将学到如何使用 SQL 访问和处理数据系统中的数据,这类数据库包括:MySQL.SQL Server.Access.Or ...

  5. c#实现图片二值化例子(黑白效果)

    C#将图片2值化示例代码,原图及二值化后的图片如下: 原图: 二值化后的图像: 实现代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...

  6. BootStrap的布局学习

    布局组件无数可复用的组件,包括字体图标.下拉菜单.导航.警告框.弹出框等更多功能. Bootstrap的使用非常灵活,可以对各种组件进行合并使用(如:为标签页项 添加带下拉菜单),下面的知识点中将逐个 ...

  7. mysql的转储SQL文件

    1.转储数据库的SQL文件,有两个选择,一是转储结构:另一种是转储数据与结构: 2.以上两种转储都不会将事件(定时器)转储,所以特别注意这个,否则以为将数据库备份完了,其实漏掉了所有的事件代码,所以需 ...

  8. cocos2dx-环境搭建和创建项目(mac用)

    学习一门语言最快的方法就是制作一个简单的项目. 而要制作一个项目必须先搭好环境,即使花上2小时去熟悉环境创建也不算浪费.由于之后的项目会用到cocos2d-x 3.0,这里以3.0为例子(不同的版本写 ...

  9. VS2010/MFC编程入门之五十(图形图像:GDI对象之画笔CPen)

    上一节中鸡啄米讲了CDC类及其屏幕绘图函数,本节的主要内容是GDI对象之画笔CPen. GDI对象 在MFC中,CGdiObject类是GDI对象的基类,通过查阅MSDN我们可以看到,CGdiObje ...

  10. VS2010/MFC编程入门之四十七(字体和文本输出:CFont字体类)

    上一节中鸡啄米讲了MFC异常处理,本节的主要内容是字体CFont类. 字体简介 GDI(Graphics Device Interface),图形设备接口,是Windows提供的一些函数和结构,用于在 ...