gpt4 book ai didi

java - 未使用Java将Java GSS-API服务票证保存在凭证缓存中

转载 作者:搜寻专家 更新时间:2023-11-01 02:20:55 27 4
gpt4 key购买 nike

我已经使用GSS-API创建了2个演示Kerberos客户端。
一个在Python3中,第二个在Java中。
这两个客户端似乎大致相同,并且两者都“起作用”,因为我得到了我的Java GSS-API服务主体所接受的服务票证。

但是在测试中,我注意到Python客户端将服务票证保存在kerberos凭证缓存中,而Java客户端似乎没有保存票证。

我使用“klist”来查看凭证缓存的内容。

我的客户端使用FreeIPA作为Kerberos环境,在Lubuntu 17.04虚拟机上运行。我正在使用OpenJDK 8 u131。

问题1: Java GSS-API是否不将服务票证保存到凭证高速缓存中?或者我可以更改代码吗?

问题2:没有将服务票证保存到缓存的事实是否有负面影响?

我的假设是,缓存的服务票证会减少与KDC的交互,但是对How to save Kerberos Service Ticket using a Windows Java client?的注释表明并非如此,但是this Microsoft technote说“客户端不需要在每次访问此特定服务器时都回到KDC”。

问题3:从Python客户端缓存的服务票证会在几分钟后消失-早于到期日期。是什么导致它们消失?

Python代码

#!/usr/bin/python3.5

import gssapi
from io import BytesIO

server_name = 'HTTP/app-srv.acme.com@ACME.COM'
service_name = gssapi.Name(server_name)

client_ctx = gssapi.SecurityContext(name=service_name, usage='initiate')
initial_client_token = client_ctx.step()

Java代码
System.setProperty("java.security.krb5.conf","/etc/krb5.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly","false");

GSSManager manager = GSSManager.getInstance();
GSSName clientName;
GSSContext context = null;

//try catch removed for brevity
GSSName serverName =
manager.createName("HTTP/app-srv.acme.com@ACME.COM", null);

Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");

//use default credentials
context = manager.createContext(serverName,
krb5Oid,
null,
GSSContext.DEFAULT_LIFETIME);

context.requestMutualAuth(false);
context.requestConf(false);
context.requestInteg(true);

byte[] token = new byte[0];
token = context.initSecContext(token, 0, token.length);

编辑:

虽然最初的问题集中在使用Java GSS-API来构建Java Kerberos Client上,但GSS不是必须的。我对在Java上工作的其他Kerberos方法持开放态度。现在,我正在尝试使用Apache Kerby kerb-client。

到目前为止,Java GSS-API似乎有两个问题:

1)它使用凭据缓存获取TGT(确定),但不缓存服务凭单(不确定)。

2)它无法访问KEYRING类型的凭据缓存。 (由行为,调试Java运行时安全性类以及该代码中的注释确认。对于Lubuntu / FreeIPA组合,我使用的是KEYRING的默认值。这不适用于Windows,可能适用于Windows不适用于其他Linux Kerberos组合。

最佳答案

编辑2:

我应该问的问题是:

由于Java GSS未使用凭据缓存,因此如何阻止我的KDC重复SGT请求。

我将原始答案留在最下面,因为如果主要集中在原始问题上。

经过另一轮深入的调试和测试,我找到了可以解决根本问题的解决方案。

在我的原始解决方案中,将Java GSS API与JAAS结合使用,与不带JAAS的“纯” GSS相比有很大的不同!

是的,凭证缓存中可能存在的现有服务票证(SGT)未加载,
也不会将任何新获取的SGT写回到缓存中,但是KDC不会经常受到冲击(真正的问题)。

纯GSS和带有JAAS的GSS都使用客户主体。该主题有一个内存中的privateCredentials集合,
用于存储TGT和SGT。

关键区别在于:

  • “纯GSS”:主题+ privateCredentials在GSSContext中创建,并且仅在GSSContext存在的情况下存在。
  • 带有JAAS的GSS的
  • :主题是由JAAS在GSSContext外部创建的,因此可以在应用程序的生命周期内有效,
    在应用程序的生命周期内跨越许多GSSContext。

  • 建立的第一个GSSContext将查询主题的privateCredentials以获取SGT,但找不到一个,
    然后向KDC请求SGT。

    SGT被添加到主题的privateCredentials中,并且随着主题的生存期超过GSSContext,
    创建以下GSSContext时,它与SGT一样可用。这些将在主题的privateCredentials中找到SGT,而无需点击KDC即可获得新的SGT。

    因此,从我的特定Java Fat Client(一次打开并且可能运行数小时)的角度来看,一切正常。
    创建的第一个GSSContext将命中SDC的KDC,然后由所有随后创建的GSSContext使用,直到关闭客户端为止。
    没有使用凭据缓存,但这不会造成伤害。

    鉴于客户的寿命要短得多,因此重新开放了很多次,也许同时开放了,
    那么使用/不使用凭据缓存可能是一个更严重的问题。
    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/app-srv.acme.com@ACME.COM", 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中。

    在此示例中,我们具有Java GSS可以访问的凭证高速缓存,其中包含有效的票证授予票证(TGT)和有效的服务票证(SGT)。

    1)创建客户端主体Subject时,将从缓存(Credentials.acquireTGTFromCache())加载TGT,并将其存储在Subject的privateCredentials集中。 ->(确定)

    仅加载TGT,不加载SGT并将其保存到主题privateCredentials。 ->(不正确)

    2)稍后,在GSSContext.initSecContext()过程的深处,安全代码实际上尝试从主题的privateCredentials检索服务票证。相关代码是Krb5Context.initSecContext()/ KrbUtils.getTicket()/ SubjectComber.find()/ findAux()。但是,由于从未在步骤1中加载SGT,所以将找不到SGT!因此,从KDC请求并使用了一个新的SGT。

    对于每个服务请求重复此步骤。

    只是出于娱乐目的,并且严格作为概念验证黑客,我在登录名和initSecContext()之间添加了几行代码来解析凭据缓存,提取凭据,转换为Krb凭据并将其添加到主题的私人凭据。

    完成此步骤后,在步骤2)中找到并使用了现有的SGT。 KDC不需要新的SGT。

    我不会发布此hack的代码,因为它调用了我们不应调用的sun内部类,并且我不希望激发其他任何人这样做。我也无意将此黑客作为解决方案。

    —>根本原因不是服务票证未保存到缓存;反而

    a)没有将SGT从凭证缓存加载到客户端主体的主题



    b)没有公共API或配置设置。

    无论有没有JAAS,这都会影响GSS-API。

    那这把我留在哪里呢?

    i)将Java GSS-API / GSS-API与JAAS“按原样”一起使用,每个SGT请求都命中KDC —>不好。

    ii)如Samson在下面的评论中所建议的,仅将Java GSS-API用于应用程序的初始登录,然后对于所有其他调用,使用 token 使用随后的调用(一种自建的kerberos-light)替代安全机制。或饼干。

    iii)考虑替代GSS-API,例如Apache Kerby kerb-client。这具有超出此答案范围的含义,并且很可能证明已从众所周知的煎锅跳到了火上。

    我已经向Oracle提交了Java功能请求,建议应该从缓存中检索SGT并将其存储在Subject凭证中(对于TGT来说已经如此)。

    http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8180144

    问题2:没有将服务票证保存到缓存的事实是否有负面影响?

    对服务票证使用凭据缓存可以减少客户端与KDC之间的交互。结果是,在未缓存服务票证的情况下,每个请求都需要与KDC进行交互,这可能导致KDC受到重创。

    关于java - 未使用Java将Java GSS-API服务票证保存在凭证缓存中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43786908/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com