由于启用了Hamza的权限机制,jdbc端已经可以正常控制权限,只需要按照jdbc的方式传送用户名和密码即可,但发现还有很多业务方是使用php的,他们只能通过thrift来访问hive。
jdbc方式的时候我们是将用户名和密码传到hiveconf中,服务通过sessionhook中解析出来的,但是thrift的方式最后放入的是HiveSession,我们只能通过反射访问到HiveSessionHookContext中的hiveSession私有属性,然后获取到用户名和密码:
public class HamzaSessionHook implements HiveSessionHook {
private static final Logger LOG = LoggerFactory
.getLogger(HamzaSessionHook.class);
@Override
public void run(HiveSessionHookContext sessionHookContext)
throws HiveSQLException {
HiveConf conf = sessionHookContext.getSessionConf();
String usr = conf.get(HamzaConstants.HAMZA_HOOK_USR);
String passwd = conf.get(HamzaConstants.HAMZA_HOOK_PASSWD);
String clientIP = conf.get(HamzaConstants.JDBC_CLIENT_IP);
if (StringUtils.isEmpty(usr) && StringUtils.isEmpty(passwd)) {
// 主要针对使用php客户端访问的时候获取用户名和密码: https://github.com/QwertyManiac/hive-hs2-php-thrift
// 由于在HiveSessionHookContext私有属性中,需要通过反射来得到
try {
Field field = sessionHookContext.getClass().getDeclaredField("hiveSession");
field.setAccessible(true);
HiveSession session = (HiveSession) field.get(sessionHookContext);
usr = session.getUsername();
passwd = session.getPassword();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
if (StringUtils.isEmpty(usr)) {
usr = HamzaConstants.DEFAULT_EMPTY_VAL;
}
if (StringUtils.isEmpty(passwd)) {
passwd = HamzaConstants.DEFAULT_EMPTY_VAL;
}
LOG.info(String
.format(
"Receiving a jdbc client request with the infomation[IP:%s, username:%s, passwd:******].",
clientIP, usr));
// store all the needs into the sessionState
SessionState ss = SessionState.get();
if (ss != null) {
Map<String, String> hiveVars = ss.getHiveVariables();
hiveVars.put(HamzaConstants.HAMZA_HOOK_LINK_FROM,
HamzaConstants.DEFAULT_HOOK_LINK_FROM);
hiveVars.put(HamzaConstants.JDBC_CLIENT_IP, clientIP);
hiveVars.put(HamzaConstants.HAMZA_HOOK_USR, usr);
hiveVars.put(HamzaConstants.HAMZA_HOOK_PASSWD, passwd);
} else {
LOG.error("SessionState is null.");
}
}
}
<?php
require_once 'thrift/Thrift/ClassLoader/ThriftClassLoader.php';
use Thrift\ClassLoader\ThriftClassLoader;
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', realpath(dirname(__FILE__)).'/thrift');
$loader->registerDefinition('org\apache\hive\service\cli\thrift', realpath(dirname(__FILE__)).'/hive');
$loader->register();
use Thrift\Type\TType;
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TSocket;
use Thrift\Transport\TBufferedTransport;
use org\apache\hive\service\cli\thrift\TCLIServiceClient;
use org\apache\hive\service\cli\thrift\TOpenSessionReq;
use org\apache\hive\service\cli\thrift\TCloseSessionReq;
use org\apache\hive\service\cli\thrift\TExecuteStatementReq;
use org\apache\hive\service\cli\thrift\TFetchResultsReq;
try {
$socket = new TSocket('192.169.45.4', '10000');
$transport = new TBufferedTransport($socket);
$protocol = new TBinaryProtocol($transport);
// Create a HS2 client
$client = new TCLIServiceClient($protocol);
// Open up the connection
$transport->open();
echo "Opened transport\n";
$sorq = new TOpenSessionReq();
$sorq->username = "bigdata_hive";
$sorq->password = "bmZY7y3smtNlRPq8";
$rorq = $client->OpenSession($sorq);
echo "Opened session\n";
$sessionHandle = $rorq->sessionHandle;
$execreq = new TExecuteStatementReq();
$execreq->sessionHandle = $sessionHandle;
$execreq->statement = "SHOW TABLES";
$execresp = $client->ExecuteStatement($execreq);
echo "Executed: ".$execreq->statement."\n";
$opHandle = $execresp->operationHandle;
$fetchreq = new TFetchResultsReq();
$fetchreq->operationHandle = $opHandle;
$fetchreq->maxRows = 10000;
$fetchres = $client->FetchResults($fetchreq);
echo "Results:\n";
foreach ($fetchres->results->rows as &$row) {
foreach ($row->colVals as $cols) {
echo $cols->stringVal->value;
}
echo "\n";
}
$scrq = new TCloseSessionReq();
$scrq->sessionHandle = $sessionHandle;
$rcrq = $client->CloseSession($scrq);
echo "Closed session\n";
// And finally, we close connection
$transport->close();
echo "Closed transport\n";
} catch (TException $tx) {
echo "ThriftException: ".$tx->getMessage()."\r\n";
}
?>