Java 使用 Kerberos 连接到 SMB 共享时出现 KrbException “Message Stream Modified (41)”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21001950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:51:23  来源:igfitidea点击:

KrbException "Message Stream Modified (41)" when connecting to SMB share using Kerberos

javakerberossambacifsjcifs

提问by Dieter Hubau

I'm having some issues with Kerberos authentication to perform file management with JCifs (Kerberos extension version 1.3.17)

我在 Kerberos 身份验证方面遇到了一些问题,无法使用 JCifs(Kerberos 扩展版本 1.3.17)执行文件管理

This is my current configuration of krb5.conf:

这是我当前的 krb5.conf 配置:

[libdefaults]
    default_realm = <REALM_NAME_UPPERCASE>
    udp_preference_limit = 1
[realms]
    <REALM_NAME_UPPERCASE> = {
        kdc = <DOMAIN_NAME_UPPERCASE>:88
        admin_server = <DOMAIN_NAME_UPPERCASE>
        default_domain = <DOMAIN_NAME_UPPERCASE>
    }
[domain_realm]
    .<domain_name> = <REALM_NAME_UPPERCASE>
    <domain_name> = <REALM_NAME_UPPERCASE>
[appdefaults]
    kinit = {
        renewable = true
        forwardable = true
    }

And this is code authenticating the user and then trying to find a file on a fileserver in the network:

这是验证用户身份然后尝试在网络中的文件服务器上查找文件的代码:

public static void main (String[] args) throws Exception {
    Subject subject = new Subject();
    System.setProperty("java.security.krb5.conf", "C:/krb5.conf");
    System.setProperty("sun.security.krb5.debug", "true");

    Map<String, Object> state = new HashMap<String, Object>();
    state.put("javax.security.auth.login.name", "USERNAME");
    state.put("javax.security.auth.login.password", "PASSWORD".toCharArray());

    Map<String, Object> options = new HashMap<String, Object>();
    options.put("debug", "true");
    options.put("useFirstPass", "true");

    Krb5LoginModule login = new Krb5LoginModule();
    login.initialize(subject, null, state, options);

    if (login.login()) {
        login.commit();
    }

    String path = "file://HOST/242269/"; // existing file server folder
    Kerb5Authenticator kerberosAuthenticator = new Kerb5Authenticator(subject);

    SmbFile smbFile = new SmbFile(path, kerberosAuthenticator);
    SmbFile[] files = smbFile.listFiles();

    for (SmbFile file : files) {
        System.out.println(file);
    }
}

Now, when I run this code, it says it can authenticate the user with those credentials (when I change the credentials, authentication fails) and it creates a ticket for this user. When I later on try to retrieve the content of a file directory over CIFS, it gives me the following error:

现在,当我运行此代码时,它说它可以使用这些凭据对用户进行身份验证(当我更改凭据时,身份验证失败)并为该用户创建一个票证。当我稍后尝试通过 CIFS 检索文件目录的内容时,它给了我以下错误:

GSSException: No valid credentials provided (Mechanism level: Message stream modified (41))
at sun.security.jgss.krb5.Krb5Context.initSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source)
at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source)
at jcifs.smb.SpnegoContext.initSecContext(SpnegoContext.java:80)
at jcifs.smb.Kerb5Authenticator.setup(Kerb5Authenticator.java:196)
at jcifs.smb.Kerb5Authenticator.access
renew_lifetime = 7d
0(Kerb5Authenticator.java:30) at jcifs.smb.Kerb5Authenticator.run(Kerb5Authenticator.java:168) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Unknown Source) at jcifs.smb.Kerb5Authenticator.sessionSetup(Kerb5Authenticator.java:166) at jcifs.smb.SmbSession.sessionSetup(SmbSession.java:320) at jcifs.smb.SmbSession.send(SmbSession.java:239) at jcifs.smb.SmbTree.treeConnect(SmbTree.java:176) at jcifs.smb.SmbFile.doConnect(SmbFile.java:925) at jcifs.smb.SmbFile.connect(SmbFile.java:974) at jcifs.smb.SmbFile.connect0(SmbFile.java:890) at jcifs.smb.SmbFile.resolveDfs(SmbFile.java:669) at jcifs.smb.SmbFile.send(SmbFile.java:783) at jcifs.smb.SmbFile.doFindFirstNext(SmbFile.java:2009) at jcifs.smb.SmbFile.doEnum(SmbFile.java:1758) at jcifs.smb.SmbFile.listFiles(SmbFile.java:1735) at jcifs.smb.SmbFile.listFiles(SmbFile.java:1668)

You can find the complete error log here(some details are obfuscated)

你可以在这里找到完整的错误日志(一些细节被混淆了)

Could someone please get me going in the right direction as to what I'm doing wrong here?

有人可以让我朝着正确的方向前进,因为我在这里做错了吗?

回答by Yahya

Uppercaseof the realm is very important to avoid "Exception: krb_error 41 Message stream modified (41)".

领域的大写是非常重要的,以避免“ Exception: krb_error 41 Message stream modified (41)”。

Seehttp://sourceforge.net/p/spnego/discussion/1003769/thread/99b3ff67/

http://sourceforge.net/p/spnego/discussion/1003769/thread/99b3ff67/

回答by Iman Akbari

Hate to necrobump but ran into the same problem when launching Spark and Zeppelin inside a Docker container, with the master being a remote Kerberos-enabled YARN cluster. However, in this case, the realm name uppercase/lowercase was notthe problem.

讨厌 necrobump,但在 Docker 容器中启动 Spark 和 Zeppelin 时遇到了同样的问题,其中 master 是远程启用 Kerberos 的 YARN 集群。但是,在这种情况下,领域名称大写/小写不是问题。

After a few hours, I found this threadwhich suggest removing the following line from the krb5.conffile:

几个小时后,我发现这个线程建议从krb5.conf文件中删除以下行:

##代码##

And that solved the issue. Hope this helps someone.

这解决了这个问题。希望这可以帮助某人。