我在修改插件以支持Kerberos身份验证方面遇到了一个奇怪的难题。
使用密码和KRB5.conf(或ini)指定以下程序时,我可以成功验证主题。
但是,当运行以下程序进行本机身份验证时,keyTab可以正常运行。问题是我的程序,比如我们称之为kerbAuth.jar
,是从在 Tomcat中调用的。
import java.io.Console;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import jcifs.Config;
import jcifs.smb.Kerb5Authenticator;
import jcifs.smb.SmbFile;
import com.sun.security.auth.module.Krb5LoginModule;
public class testKRB
{
private static String URL = "smb://192.168.101.141/Share/";
private static String KDC = "192.168.101.2";
private static String REALM = "REALM.NET";
private static String KRB = "/opt/app/config/krb5.ini";
private static String KEYTAB = null;
private static String PRINCIPAL = "user@REALM.NET";
public static void main(String[] args) throws LoginException
{
Console console = System.console();
KEYTAB = console.readLine("Enter keytab path:");
Config.setProperty("jcifs.smb.client.capabilities",Kerb5Authenticator.CAPABILITIES);
Config.setProperty("jcifs.smb.client.flags2",Kerb5Authenticator.FLAGS2);
Config.setProperty("jcifs.smb.client.signingPreferred", "true");
try
{
Subject subject = new Subject();
login(subject);
// List SMB files as a test.
System.out.println("Files:");
SmbFile file = new SmbFile(URL, new Kerb5Authenticator(subject));
SmbFile[] files = file.listFiles();
for( int i = 0; i < files.length; i++ ) {
System.out.println( "-->" + files[i].getName() );
}
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void login(Subject subject) throws LoginException
{
Map<String, Object> state = new HashMap<String, Object>();
state.put("java.security.krb5.conf", KRB);
Map<String, Object> option = new HashMap<String, Object>();
option.put("debug", "true");
option.put("debug", "true");
option.put("principal", PRINCIPAL);
option.put("useKeyTab", "true");
option.put("keyTab", KEYTAB);
option.put("refreshKrb5Config", "true");
option.put("doNotPrompt", "true");
option.put("storeKey", "true");
Krb5LoginModule login = new Krb5LoginModule();
login.initialize(subject, null, state, option);
if(login.login())
{
login.commit();
}
}
上述解决方案在独立调用时效果很好。
从Tomcat中调用时,出现以下错误:
SEVERE: [Console] Error authenticating Subject: java.security.AccessControlException: access denied (javax.security.auth.AuthPermission modifyPrivateCredentials)
在进行登录提交后运行subject.getPrincipals().toString()
,我检索了Principal user@REALM.NET
。
查看KRB5调试日志:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator true KeyTab is /opt/app/plugins/user.keytab refreshKrb5Config is false principal is user@REALM.NET tryFirstPass is false useFirstPass is false storePass is false clearPass is false
principal's key obtained from keytab
Aquire TGT using AS Exchange
principal is user@REALM.NET
EncryptionKey: keyType=18 keyBytes (hex dump)=0000; ......
java.security.AccessControlException: access denied (javax.security.auth.AuthPermission modifyPrivateCredentials)
这告诉我,我可以阅读keyTab就好了,我可以阅读校长(我认为是私人的,但如果我错了,请纠正我。)
为了解决AuthPermission错误,我做了两件事。
1)在我的主题初始化中添加了AuthPermissions:
state.put("javax.security.auth.AuthPermission", "doAs");
state.put("javax.security.auth.AuthPermission", "modifyPrincipals");
state.put("javax.security.auth.AuthPermission", "modifyPublicCredentials");
state.put("javax.security.auth.AuthPermission", "modifyPrivateCredentials");
2)将这些相同的权限添加到java.policy(在该Java空间中):
grant codeBase "file:/opt/app/plugins/kerbAuth.jar"
{
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.AuthPermission "modifyPublicCredentials";
permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
};
3)还尝试修改Catalina的manager.policy:
grant codeBase "file:/opt/app/tomcat/lib/-"
{
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.AuthPermission "modifyPublicCredentials";
permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
};
然而,Catalina / Tomcat已经允许AllPermissions
插件/小程序。
看起来storeKey
调用是罪魁祸首的一部分,但如果不这样做,我必须将isInitiator
设置为true
以获得执行的提交(但不是实际上根据Wireshark与Active Directory通信,但TGT没有保存。
我正在寻找的是我可以在调试中采取的任何额外步骤,我需要设置AuthPermissions,无论是Tomcat还是其他类似,或者这是否是我在其他地方没有考虑的问题Tomcat中。
Java版本:1.6.0_31(应用程序的本机,而不是系统)