天天看點

開發中遇到cannot get Kerberos realm的問題,如何解決

作者:時間旅行vlog

場景:開發中突然遇到了cannot get Kerberos realm的認證問題,但是Kerberos認證是必須的,又不能更改伺服器配置,業務代碼中該如何實作呢?

開發中遇到cannot get Kerberos realm的問題,如何解決

這是Kerberos認證問題,廢話不多說了,直接上代碼:

@Slf4j

public class KerberosUtils {

public static final KerberosUtils singleton = new KerberosUtils();

public static final String KRB5_CONF_KEY = "java.security.krb5.conf";

public static final String HADOOP_AUTH_KEY = "hadoop.security.authentication";

public static final String KRB_STR = "Kerberos";

public static final String FALSE_STR = "false";

public static final String KRB5_DEBUG = "sun.security.krb5.debug";

public static final String SUBJECT_ONLY_KEY = "javax.security.auth.useSubjectCredsOnly";

public void loginFromKeytab(String kerberosUserName,

String keytabFile,

String kerberosPrincipal){

//事先kinit -kt 認證

execLocalCommands(buildKinit(keytabFile,kerberosPrincipal));

System.setProperty(KRB5_CONF_KEY,"/etc/krb5.conf");

String var1 = System.getProperty(KRB5_CONF_KEY);

System.out.println("conf::"+var1);

Configuration conf = new Configuration();

conf.set(HADOOP_AUTH_KEY, "Kerberos");

conf.setBoolean("hadoop.security.authorization", true);

UserGroupInformation.setConfiguration(conf);

try {

log.info("kerberos - userName:{},isLoginKeytabBased:{}", UserGroupInformation.getLoginUser().getUserName(), UserGroupInformation.isLoginKeytabBased());

UserGroupInformation.loginUserFromKeytab( kerberosUserName, keytabFile);

System.out.println("!(UserGroupInformation.getLoginUser().getUserName().equals(kerberosUserName):"+UserGroupInformation.getLoginUser().getUserName().equals(kerberosUserName));

} catch (IOException e) {

e.printStackTrace();

}

}

public String buildKinit(String keytabFile ,String kerberosPrincipal) {

String url = String.format("kinit -kt %s %s", keytabFile, kerberosPrincipal);

log.info("kerbers init : {}", url);

return url;

}

public UserGroupInformation loginAndReturnUgi(String principal, String keytabPath, String krb5confPath) throws IOException {

log.info("Kerberos login with principal: {} and keytab: {}", principal, keytabPath);

reloadKrb5conf(krb5confPath);

Configuration configuration = new Configuration();

configuration.set(HADOOP_AUTH_KEY, KRB_STR);

UserGroupInformation.setConfiguration(configuration);

return UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytabPath);

}

//在jaas.conf中為KRB5LoginModule設定refreshKrb5Config = true

public synchronized void reloadKrb5conf(String krb5confPath) {

System.setProperty(KRB5_CONF_KEY, krb5confPath);

// 不重新整理會讀/etc/krb5.conf

try {

Config.refresh();

String defaultRealm = KerberosUtil.getDefaultRealm();

} catch (KrbException e) {

log.warn( "resetting default realm failed, current default realm will still be used.", e);

}

}

private void execLocalCommands(String kinit){

try{

log.info("Now executed linux command is :{} ", kinit);//輸出下指令

final Process process = Runtime.getRuntime().exec(kinit);

new Thread(){

@Override

public void run(){

BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));

String line = null;

try{

while((line = in.readLine()) != null){

log.info("kinit input: " + line);

}

} catch (IOException e){

log.error(e.getMessage());

} finally {

in.close();

}

}.start();

new Thread(){

@Override

public void run(){

BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));

String line = null;

try{

while((line = err.readLine()) != null){

log.info("kinit err: " + line);

}

} catch (IOException e){

log.error(e.getMessage());

}finally{

err.close();

}

}.start();

process.waitFor();

}catch (InterruptedException e) {

log.error(e.getMessage());

} catch (IOException e) {

log.error(e.getMessage());

}

}

}

調用該工具類

KerberosUtils.singleton.loginFromKeytab(db.getUserName(), db.getKerberosFile(), db.getKerberosPrincipal());

就OK了!

​編輯​

繼續閱讀