【发布时间】:2019-09-25 04:39:40
【问题描述】:
我尝试生成可用作 HTTP 标头的令牌,以对 HDFS WebHDFS URL 和 Oozie REST API URL 进行身份验证。 我引用了下面的 url 以使用下面的代码生成 Negotiate 令牌。 https://www.ibm.com/support/knowledgecenter/en/SS7JFU_8.5.5/com.ibm.websphere.express.doc/ae/tsec_SPNEGO_token.html
public class TokenCreation {
private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
public static byte[] genToken(String principal) {
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
byte[] spnegoToken = new byte[0];
try {
Oid spnegoMechOid = new Oid(SPNEGO_OID);
Oid krb5MechOid = new Oid(KERBEROS_OID);
GSSCredential clientGssCreds = null;
GSSManager manager = GSSManager.getInstance();
GSSName gssUserName = manager.createName(principal, GSSName.NT_USER_NAME, krb5MechOid);
clientGssCreds = manager.createCredential(gssUserName.canonicalize(krb5MechOid),
GSSCredential.INDEFINITE_LIFETIME,
krb5MechOid,
GSSCredential.INITIATE_ONLY);
clientGssCreds.add(gssUserName,
GSSCredential.INDEFINITE_LIFETIME,
GSSCredential.INDEFINITE_LIFETIME,
spnegoMechOid, GSSCredential.INITIATE_ONLY);
GSSName gssServerName = manager.createName(principal, GSSName.NT_USER_NAME);
GSSContext clientContext = manager.createContext(gssServerName.canonicalize(spnegoMechOid),
spnegoMechOid,
clientGssCreds,
GSSContext.DEFAULT_LIFETIME);
// optional enable GSS credential delegation
clientContext.requestCredDeleg(true);
// create a SPNEGO token for the target server
spnegoToken = clientContext.initSecContext(spnegoToken, 0, spnegoToken.length);
} catch (GSSException e) {
e.printStackTrace();
}
return spnegoToken;
}
但是运行上面的代码后,总是得到如下提示:
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.c.u.security.KrbUtils - after loginUserFromKeytab............AtoimcUser:HTTP/host1.exmaple.com@EXAMPLE.COM
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.app.oozie.OozieAppCaller - ->>>>>>User Name is HTTP/host1.exmaple.com@EXAMPLE.COM
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.app.oozie.OozieAppCaller - ->>>>>>Mode is KERBEROS
>>>KinitOptions cache name is /tmp/krb5cc_0
Kerberos username [root]: ^C^C^C
Kerberos password for root:
您可以在上面的输出日志的末尾看到。 “Kerberos 用户名”总是提示询问用户名。
我还尝试手动运行 kinit keytab。 上面的类可以成功生成令牌。 但是手动运行 kinit 不是我想要的方式。
你能帮忙吗? 谢谢。
【问题讨论】:
-
我做了一些搜索,发现上面的 TokenCreation 类在运行 UserGroupInformation.loginUserFromKeytab 后似乎无法生成令牌?
-
你能解释一下为什么你搞乱了低级别的 Kerberos 凭据管理,而本机 Java HTTP 客户端支持开箱即用的 SPNego? (其他 HTTP 客户端,例如来自 Apache 的客户端可能存在错误)
-
Hadoop
UserGroupInformation使用自定义库(部分)覆盖 Kerberos 的默认 Java 实现(在 JAAS 内部),原因有好有坏(两种实现都有限且脆弱且难以无论如何调试)——当你使用 UGI 来“从 keytab 登录”时,它总是会创建一个 private 票证,该票证不会被推送到票证缓存中。因此,您不能从 JAAS 使用它。 -
要在 JAAS 中启用调试跟踪(转储到 StdOut / StdErr),请使用
-Dsun.security.krb5.debug=true和-Djava.security.debug=gssloginconfig,configfile,configparser,logincontext>> 输出并不漂亮,正如您可以从加密库中所期望的那样... -
...以及
-Dsun.security.spnego.debug=true使用本机 HTTP 客户端时