Java 使用GSSAPI从有效的ldap服务票证创建LdapContext
请注意:-我只想验证是否可以使用JAAS/GSSAPI实现以下目标。我找不到任何指针 首先,让我澄清我的应用程序的限制:Java 使用GSSAPI从有效的ldap服务票证创建LdapContext,java,kerberos,jndi,jaas,gssapi,Java,Kerberos,Jndi,Jaas,Gssapi,请注意:-我只想验证是否可以使用JAAS/GSSAPI实现以下目标。我找不到任何指针 首先,让我澄清我的应用程序的限制: 我们不能有一个静态的krb.conf文件。它是动态的、不断变化的。因此,在内存中缓存LoginContext对象是不可能的,因为一旦krb.conf文件被修改,主体的凭据就会失效 我们想要管理大量领域,而这些领域我们没有任何先验信息,因此静态krb.conf文件是不可能的 “sun.security.krb5.internal.tools.Kinit”是专有的,并且总是会收到
sun.security.krb5.internal.tools.Kinit
”是专有的,并且总是会收到一条警告,它可能在将来的版本中被删除。因此,我们不能使用它来生成缓存,因为存在获得运行时问题的风险。注意:即使krb.conf文件本机更改,缓存的TGT也不会过期。但是这里的问题是,我们必须使生成和维护krb.conf文件的代码变得非常复杂。我们希望避免这种情况 System.setProperty("java.security.krb5.conf", "C:\\Windows\\krb5.ini");
System.setProperty("sun.security.jgss.debug","true");
LoginContext lc = null;
try {
lc = new LoginContext(LdapCtxGSSAPIEx.class.getName(),
new LoginCallbackHandler(username,password));
// Attempt authentication
// You might want to do this in a "for" loop to give
// user more than one chance to enter correct username/password
lc.login();
} catch (LoginException le) {
System.err.println("Authentication attempt failed" + le);
System.exit(-1);
}
解决方案#1:
创建有效的LoginContext
后,使用GSSAPI获取ldap的服务票证。我知道另一种在PrivilegedAction#run()中形成LdapContext的方法(实际上是我们当前的实现,如解决方案2所示)。但这对缓存没有帮助。因此,尝试使用PoC来存储服务票证,而不是TGT获取ldap服务票证如下所示:
// servicePrincipalName = ldap/ad01.example.lab@EXAMPLE.LAB
GSSManager manager = GSSManager.getInstance();
GSSName serverName = manager.createName( servicePrincipalName,
GSSName.NT_HOSTBASED_SERVICE);
final GSSContext context = manager.createContext( serverName, krb5OID, null,
GSSContext.DEFAULT_LIFETIME);
// The GSS context initiation has to be performed as a privileged action.
byte[] serviceTicket = Subject.doAs( subject, new PrivilegedAction<byte[]>() {
public byte[] run() {
try {
byte[] token = new byte[0];
// This is a one pass context initialisation.
context.requestMutualAuth( false);
context.requestCredDeleg( false);
return context.initSecContext( token, 0, token.length);
}
catch ( GSSException e) {
e.printStackTrace();
return null;
}
}
});
当此行:DirContext ctx=new InitialDirContext(env)执行上述代码中的code>:使用带有服务主体的新的PrivateCredential
填充主题。示例。lab@EXAMPLE.LAB
问题:我是否可以存储此服务票证以供进一步参考,从而创建LdapContext,而不是一次又一次地执行所有身份验证步骤
什么是授权证书?他们会帮助解决我的问题吗
更新:
为什么要在缓存中存储服务票证而不是TGT?-->为了避免显式的扭结。存储服务票据将很容易与我们当前的解决方案相适应。此外,这将是一个临时解决方案,因为我们将根据客户的需要向他们询问krb.conf文件,并免除创建krb.conf文件的责任。但现在,我们必须这样做
请帮忙
// servicePrincipalName = ldap/ad01.example.lab@EXAMPLE.LAB
GSSManager manager = GSSManager.getInstance();
GSSName serverName = manager.createName( servicePrincipalName,
GSSName.NT_HOSTBASED_SERVICE);
final GSSContext context = manager.createContext( serverName, krb5OID, null,
GSSContext.DEFAULT_LIFETIME);
// The GSS context initiation has to be performed as a privileged action.
byte[] serviceTicket = Subject.doAs( subject, new PrivilegedAction<byte[]>() {
public byte[] run() {
try {
byte[] token = new byte[0];
// This is a one pass context initialisation.
context.requestMutualAuth( false);
context.requestCredDeleg( false);
return context.initSecContext( token, 0, token.length);
}
catch ( GSSException e) {
e.printStackTrace();
return null;
}
}
});
DirContext ctx = Subject.doAs(lc.getSubject(), new JndiAction<DirContext>(args,providerURL ));
class JndiAction<DirContext> implements java.security.PrivilegedAction<DirContext> {
.......
public DirContext run() {
return performJndiOperation(args, this.providerURL);
}
public DirContext performJndiOperation(String[] args, String providerURL){
......
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
// Must use fully qualified hostname
env.put(Context.PROVIDER_URL, providerURL);
// Request the use of the "GSSAPI" SASL mechanism
// Authenticate by using already established Kerberos credentials
env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
// Request mutual authentication
env.put("javax.security.sasl.server.authentication", "true");
DirContext ctx = new InitialDirContext(env);
return ctx;
......
}
.......
}