Изменить 2:
Мне следовало задать следующий вопрос:
Как сделать так, чтобы мой KDC не зависал от повторных запросов SGT, потому что Java GSS не использует кеш учетных данных.
Я оставляю свой исходный ответ внизу, потому что он в основном сосредоточен на исходном вопросе.
После очередного раунда глубокой отладки и тестирования я нашел приемлемое решение основной проблемы.
Использование Java GSS API с JAAS, в отличие от "чистого" GSS без JAAS в моем исходном решении, имеет большое значение!
Да, существующие сервисные билеты (SGT), которые могут находиться в кэше учетных данных, не загружаются, и никакие вновь приобретенные SGT не записываются обратно в кэш, однако KDC не подвергается постоянному воздействию (настоящая проблема).
И чистый GSS, и GSS с JAAS используют основную тему клиента. У субъекта есть набор privateCredentials в памяти, который используется для хранения TGT и SGT.
Ключевое отличие:
«чистый GSS»: объект + privateCredentials создается в GSSContext и живет только до тех пор, пока живет GSSContext.
GSS с JAAS: объект создается JAAS вне GSSContext и, таким образом, может существовать в течение всего жизненного цикла приложения, охватывая множество GSSContexts в течение всего жизненного цикла приложения.
Первый установленный GSSContext будет запрашивать личные учетные данные субъекта для SGT, но не находить его, а затем запрашивать SGT от KDC.
SGT добавляется к privateCredentials субъекта, и, поскольку субъект живет дольше, чем GSSContext, он доступен, как и SGT, при создании следующих GSSContexts. Они найдут SGT в личных учетных данных субъекта, и им не нужно нажимать KDC для нового SGT.
Итак, в свете моего конкретного Java Fat Client, открытого один раз и, вероятно, работающего часами, все в порядке. Первый созданный GSSContext попадет в KDC для SGT, который затем будет использоваться всеми последующими созданными GSSContexts, пока клиент не будет закрыт. Кэш учетных данных не используется, но это не повредит.
В свете гораздо более короткоживущего клиента, который открывался много раз и, возможно, параллельно, использование / неиспользование кеша учетных данных может быть более серьезной проблемой.
private void initJAASandGSS() {
LoginContext loginContext = null;
TextCallbackHandler cbHandler = new TextCallbackHandler();
try {
loginContext = new LoginContext("wSOXClientGSSJAASLogin", cbHandler);
loginContext.login();
mySubject = loginContext.getSubject();
} catch (LoginException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gssManager = GSSManager.getInstance();
try {
//TODO: LAMB: This name should be got from config / built from config / serviceIdentifier
serverName = gssManager.createName("HTTP/[email protected]", null);
Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");
} catch (GSSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String getGSSwJAASServiceToken() {
byte[] token = null;
String encodedToken = null;
token = Subject.doAs(mySubject, new PrivilegedAction<byte[]>(){
public byte[] run(){
try{
System.setProperty("javax.security.auth.useSubjectCredsOnly","true");
GSSContext context = gssManager.createContext(serverName,
krb5Oid,
null,
GSSContext.DEFAULT_LIFETIME);
context.requestMutualAuth(false);
context.requestConf(false);
context.requestInteg(true);
byte[] ret = new byte[0];
ret = context.initSecContext(ret, 0, ret.length);
context.dispose();
return ret;
} catch(Exception e){
Log.log(Log.ERROR, e);
throw new otms.util.OTMSRuntimeException("Start Client (Kerberos) failed, cause: " + e.getMessage());
}
}
});
encodedToken = Base64.getEncoder().encodeToString(token);
return encodedToken;
}
Конец редактирования 2: исходный ответ ниже:
Вопрос 1: Java GSS-API не сохраняет билеты службы в кэш учетных данных? Или я могу так изменить свой код?
Изменить: анализ первопричин.
После многих часов отладки классов sun.security. * Я теперь понимаю, что код GSS и Java Security делает / не делает - по крайней мере, в Java 8 u 131.
В этом примере у нас есть кеш учетных данных типа, к которому GSS может получить доступ, содержащий действительный билет предоставления билета (TGT) и действительный билет службы (SGT).
1) Когда создается субъект-клиент-участник, TGT загружается из кеша (Credentials.acquireTGTFromCache ()) и сохраняется в наборе privateCredentials субъекта. -> (ОК)
Загружается только TGT, SGT НЕ загружаются и не сохраняются в Subject privateCredentials. -> (НЕ ОК)
2) Позже, глубоко в процессе GSSContext.initSecContext (), код безопасности фактически пытается получить служебный билет из privateCredentials субъекта. Соответствующий код - Krb5Context.initSecContext () / KrbUtils.getTicket () / SubjectComber.find () / findAux (). Однако, поскольку SGT никогда не загружались на шаге 1) SGT не будет найден! Поэтому новый SGT запрашивается у KDC и используется.
Это повторяется для каждого запроса на обслуживание.
Просто для удовольствия и строго в качестве хака для проверки концепции, я добавил несколько строк кода между логином и initSecContext (), чтобы проанализировать кеш учетных данных, извлечь учетные данные, преобразовать их в учетные данные Krb и добавить их в личные учетные данные Субъекта.
Это сделано на шаге 2) существующий SGT найден и используется. Никаких новых SGT от KDC не запрашивается.
Я не буду публиковать код этого взлома, поскольку он вызывает внутренние классы sun, которые мы не должны вызывать, и я не хочу никого вдохновлять на это. Я также не собираюсь использовать этот хак в качестве решения.
-> Основная причина проблемы заключается не в том, что билет службы не СОХРАНЕН в кэш; скорее
a) что SGT не ЗАГРУЖАЕТСЯ из кэша учетных данных в Субъект клиента-участника.
а также
б) что для этого нет общедоступного API или настроек конфигурации.
Это влияет на GSS-API как с JAAS, так и без него.
Так что же мне остается?
i) Используйте Java GSS-API / GSS-API с JAAS «как есть», при этом каждый запрос SGT попадает в KDC -> Плохо.
ii) Как предлагает Самсон в комментариях ниже, используйте Java GSS-API только для первоначального входа в приложение, затем для всех дальнейших вызовов используйте альтернативный механизм безопасности для последующих вызовов (своего рода самодельный kerberos-light) с использованием токенов. или куки.
iii) Рассмотрите альтернативы GSS-API, такие как Apache Kerby curb-client. Это имеет значение, выходящее за рамки этого ответа, и вполне может оказаться прыжком с пресловутой сковороды на огонь.
Я отправил Oracle Feature Request Java, предлагая, чтобы SGT были извлечены из кеша и сохранены в учетных данных Subject (как уже было в случае с TGT).
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8180144
Вопрос 2: Есть ли обратная сторона того факта, что билет службы не сохраняется в кеше?
Использование кеша учетных данных для сервисных билетов сокращает взаимодействие между клиентом и KDC. Следствием этого является то, что там, где служебные билеты не кэшируются, каждый запрос потребует взаимодействия с KDC, что может привести к тому, что KDC будет заблокирован.
person
FlyingSheep
schedule
07.05.2017