啥都不说,先吐槽,吐槽技术中心,吐槽部门,能不能让我安安全全的使用,不要扔个个东西来就让我用,在开发环境没有kerberos,来了上正式,直接给布上,你让我这连kerberos都不知道是啥的java开发人员咋搞,完,写一下自己通过连接池连接存在kerberos认证的impala+kudu数据库。
“Kerberos 服务”是一种客户机/服务器体系结构,用于在网络上提供安全事务。该服务可提供功能强大的用户验证以及完整性和保密性。通过验证,可保证网络事务的发送者和接收者的身份真实。该服务还可以检验来回传递的数据的有效性(完整性),并在传输过程中对数据进行加密(保密性)。使用 Kerberos 服务,可以安全登录到其他计算机、执行命令、交换数据以及传输文件。此外,该服务还提供授权服务,这样,管理员便可限制对服务和计算机的访问。而且,作为 Kerberos 用户,您还可以控制其他用户对您帐户的访问。
当时先在网上找资料,发现网上没有连接池连接的,只有通过JDBC直连的,代码如下:
public class App4 {
public static void main(String[] args) throws ClassNotFoundException {
String driverName="org.apache.hive.jdbc.HiveDriver";
Class.forName("org.apache.hive.jdbc.HiveDriver");
String url = "jdbc:hive2://135.12.70.35:21055/;principal=impala/[email protected]";
Configuration conf = new Configuration();
conf.set("hadoop.security.authentication", "Kerberos");
try {
System.setProperty("java.security.krb5.conf", "resource/krb5.conf");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab("impala/[email protected]", "resource/impala.haproxy.keytab");
} catch (IOException e) {
e.printStackTrace();
}
try {
Class.forName(driverName);
Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
String sql = "select * from test1";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getInt(1));
}
stmt.close();
rs.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
通过上面发现,咋的,连接前先验证,但是连接池的init方法根本不用我写,这个咋搞,这时候我的思维进入了误区,想是不是需要修改连接池的源码,所以我写了了类继承DruidDataSource,重写了init方法在这上面加上kerberos验证,但是这种方法能实现,其实很错误,这可能我受了传统数据库的影响,以为每次建立连接都得验证,其实kerberos是单点登陆的,是服务器之间的通信,后来在领导的指导下,我采用了listener在项目启动时,对项目启动时验证,监听器如下:
public class GetConnListener implements ServletContextListener{
private static Logger log = LoggerFactory.getLogger(GetConnListener.class) ;
private static final Configuration kuduconf = new Configuration();
public static void initkerberos() throws IOException
{
File directory = new File("");// 参数为空
String courseFile = directory.getCanonicalPath();
Configuration conf = getKuduConf();
try {
System.setProperty("java.security.krb5.conf", courseFile+"/WebRoot/krb5.conf");
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab("[email protected]", courseFile+"/WebRoot/impala.haproxy.keytab");
} catch (IOException e) {
e.printStackTrace();
}
log.info("Kerberos验证程序") ;
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
try {
initkerberos();
} catch (IOException e) {
e.printStackTrace();
}
log.info("Kerberos初始化完成") ;
}
public static Configuration getKuduConf(){
kuduconf.set("hadoop.security.authentication", "Kerberos");
return kuduconf;
}
}
值得注意的是监听器的顺序,认证的这个监听器放在最上面,如下:
sjgl.system.GetConnListener
org.springframework.web.context.ContextLoaderListener
但是不知道我看kerberos好像24小时失效,然后写了个定时任务及时认证,但是好像认证一次就不需要重复认证,他自己刷新,我也没管,保险起见,调度如下:
@Service
public class reloadkbs {
private static Logger log = LoggerFactory.getLogger(reloadkbs.class) ;
@Scheduled(fixedRate = 1000*60*60*23)
public void reloadkerberos() throws IOException{
GetConnListener.initkerberos();
log.info("Kerberos重新验证完成") ;
}
}
但是在使用连接池时也遇到过连接池的问题例如,连接池隔一天断开,重启服务正常,错误提示:[Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not inspect JDBC autocommit mode] with root cause
java.net.SocketException: Software caused connection abort: socket write error
我按照druid的示例配置了最小连接数,以及检测连接打开,但是没用的?请问怎么看druid的保持连接池最小连接的检测日志输出???我看看有没有检测连接。
解决方案:首先更改wait_timeout是不好的。
用如下配置可以解决:
testWhileIdle:建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于
timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
testOnBorrow:申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn:归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
另外:大家七夕快乐,今年七夕我还是一个人。