linux docker容器中的Windows身份验证

Sch*_*ltz 17 kerberos windows-authentication gssapi http-negotiate gss

我正在尝试在 kubernetes 下的 linux docker 容器中使用 windows 身份验证。

我正在关注此设置:https : //docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio#kestrel

应用程序在 .net core3 中,使用 nuget Microsoft.AspNetCore.Authentication.Negotiate 并在 kestrel 中运行

我已经添加了

services.AddAuthentication(Microsoft.AspNetCore.Authentication.Negotiate.NegotiateDefaults.AuthenticationScheme).AddNegotiate();
Run Code Online (Sandbox Code Playgroud)

app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)

并将我的 devbase 映像设置为

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y

ADD ca/ca.crt /usr/local/share/ca-certificates/ca.crt
RUN chmod 644 /usr/local/share/ca-certificates/*
RUN update-ca-certificates


RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user

COPY krb5.conf /etc/krb5.conf
RUN mkdir /app

RUN echo BQIAAA..== | base64 -d > /app/is.k01.HTTP.keytab
WORKDIR /app

#RUN docker version

RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --shell /bin/bash -d /app app

RUN apt install -y mc sudo syslog-ng realmd gss-ntlmssp
Run Code Online (Sandbox Code Playgroud)

tfs 管道中的构建创建从上面派生的应用程序 docker 映像并添加以下环境变量,还将构建复制到 /app

RUN chmod 0700 run.sh
ENV KRB5_KTNAME=/app/is.k01.HTTP.keytab
ENV KRB5_TRACE=/dev/stdout
ENV ASPNETCORE_URLS=http://*:80;https://+:443
RUN chown app:app /app -R
USER app
Run Code Online (Sandbox Code Playgroud)

该应用程序由 run.sh 运行

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y

ADD ca/ca.crt /usr/local/share/ca-certificates/ca.crt
RUN chmod 644 /usr/local/share/ca-certificates/*
RUN update-ca-certificates


RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user

COPY krb5.conf /etc/krb5.conf
RUN mkdir /app

RUN echo BQIAAA..== | base64 -d > /app/is.k01.HTTP.keytab
WORKDIR /app

#RUN docker version

RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --shell /bin/bash -d /app app

RUN apt install -y mc sudo syslog-ng realmd gss-ntlmssp
Run Code Online (Sandbox Code Playgroud)

klist 列出已将 SPN 分配给机器的主体

在 ie 和 firefox 中,我已将 network.negotiate-auth.trusted-uris 添加到我的应用程序中

但是我收到登录对话框但登录失败

所以问题是:

如何使用 Microsoft.AspNetCore.Authentication.Negotiate 包启用调试日志?

我的假设是这个包不能正确地与 kerberos 通信,也许某些包丢失了,没有运行或什么的。

另请注意,容器和 .net 应用程序已成功连接到域,因为我使用集成安全性连接到有效的数据库。

**** 编辑 > 回答第一部分

要启用日志,应该在 kestrel 中启用日志:在 appsettings.json 中:

  "Logging": {
    "LogLevel": {
      "Default": "Debug",
    }
  },
Run Code Online (Sandbox Code Playgroud)

在 program.cs 中:

RUN chmod 0700 run.sh
ENV KRB5_KTNAME=/app/is.k01.HTTP.keytab
ENV KRB5_TRACE=/dev/stdout
ENV ASPNETCORE_URLS=http://*:80;https://+:443
RUN chown app:app /app -R
USER app
Run Code Online (Sandbox Code Playgroud)

在 Startup.cs 中,可以跟踪协商事件:

service syslog-ng start
kinit HTTP/is.k01.mydomain.com@MYDOMAIN.COM -k -t /app/is.k01.HTTP.keytab
klist
dotnet dev-certs https
dotnet /app/SampleApi.dll
Run Code Online (Sandbox Code Playgroud)

**** 编辑

同时,根据我在 .net core docker web 应用程序中允许 windows 身份验证的目标,我正在浏览 .net core 和 corefx 的源代码,并将身份验证代码截断到此示例控制台应用程序:

  "Logging": {
    "LogLevel": {
      "Default": "Debug",
    }
  },
Run Code Online (Sandbox Code Playgroud)

所以,我发现与库相通 System.Net.NTAuthentication 有连通与 System.Net.Security.NegotiateStreamPal 与UNIX版本的通信 Interop.NetSecurityNative.InitSecContext

这应该以某种方式触发 os 中的 GSSAPI

在 dotnet 运行时 git 中,他们告诉我们 gss-ntlmssp 需要 gss-ntlmssp 才能工作,即使在 aspnet 核心文档中没有提到它。

https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=gss-ntlmssp

尽管如此,我已经编译了 gss-ntlmssp 并发现如果没有这个库,它会抛出错误“请求了不受支持的机制。 ”。对于我的库,它会引发错误“未提供凭据,或者凭据不可用或无法访问。 ”,但从不访问任何 gss_* 方法。

我已经通过将日志条目添加到从未发生过的文件来测试 gss 方法的使用..fe:

Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
    logging.AddFilter("Microsoft", LogLevel.Debug);
    logging.AddFilter("System", LogLevel.Debug);
    logging.ClearProviders();
    logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
Run Code Online (Sandbox Code Playgroud)

所以.net调用gssapi,gssapi不调用机制。

我在 centos7 vm、ubuntu windows 子系统和 debian docker 镜像(定制的 mcr.microsoft.com/dotnet/core/sdk:3.1-buster)中观察到了相同的行为

所以现在的问题是,我如何调试 gssapi ?

我假设我当前的 gssapi 是由这个库管理的:

readelf -d /usr/lib64/libgssapi_krb5.so
Run Code Online (Sandbox Code Playgroud)
Dynamic section at offset 0x4aa48 contains 34 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libkrb5.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libk5crypto.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libcom_err.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libkrb5support.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libkeyutils.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libresolv.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libgssapi_krb5.so.2]
 0x000000000000000c (INIT)               0xb1d8
 0x000000000000000d (FINI)               0x3ebcc
 0x0000000000000019 (INIT_ARRAY)         0x24a120
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x24a128
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x1f0
 0x0000000000000005 (STRTAB)             0x3048
 0x0000000000000006 (SYMTAB)             0x720
 0x000000000000000a (STRSZ)              9167 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x24b000
 0x0000000000000002 (PLTRELSZ)           8088 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x9240
 0x0000000000000007 (RELA)               0x58b0
 0x0000000000000008 (RELASZ)             14736 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffc (VERDEF)             0x5788
 0x000000006ffffffd (VERDEFNUM)          3
 0x000000006ffffffe (VERNEED)            0x57e0
 0x000000006fffffff (VERNEEDNUM)         4
 0x000000006ffffff0 (VERSYM)             0x5418
 0x000000006ffffff9 (RELACOUNT)          504
 0x0000000000000000 (NULL)               0x0
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经从 mit 源代码编译了新的最新 gssapi,并发现它向我抛出错误“请求了不受支持的机制”。因为 gssapi 需要未提供的 gss 解释器。在 centos7 中,我遇到了另一个问题,即 openssl 库使用了不兼容的共享 kerberos 库,因此 yum 停止工作。

*** 编辑

我发现 gss-ntlmssp 具有标志 GSS_C_MA_NOT_DFLT_MECH 因此它失败并显示消息“未提供凭据,或者凭据不可用或无法访问。”。解决方案是构建没有此属性的自定义 gss-ntlmssp,因为我希望将其用作默认身份验证机制。

我的用于检查凭据的示例控制台应用程序现在可以正常工作,我现在将尝试将它放在 docker 容器中。

*** 编辑

我能够在 kubernetes 中成功运行我的 ConsoleApp:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y

ADD ca/ca.crt /usr/local/share/ca-certificates/ca.crt
RUN chmod 644 /usr/local/share/ca-certificates/*
RUN update-ca-certificates


RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user

RUN mkdir /app

RUN apt install -y mc sudo syslog-ng python3-software-properties software-properties-common packagekit git gssproxy vim
RUN apt install -y autoconf automake libxslt-dev doxygen findutils libgettextpo-dev libtool m4 make libunistring-dev libssl-dev zlib1g-dev gettext xsltproc libxml2-utils libxml2-dev xml-core docbook-xml docbook-xsl bison libkrb5-dev
RUN systemctl enable syslog-ng
RUN mkdir /src 
RUN cd /src && wget https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-1.18.tar.gz
RUN cd /src && tar -xf krb5-1.18.tar.gz
RUN cd /src/krb5-1.18/src && ./configure && make && make install

RUN cd /src && git clone https://github.com/scholtz/gss-ntlmssp.git 
RUN cd /src/gss-ntlmssp/ && autoreconf -f -i && ./configure && make && make install
RUN cp /src/gss-ntlmssp/examples/mech.ntlmssp.conf /etc/gss/mech.d/mech.ntlmssp.conf

COPY testgss /testgss
RUN cd /testgss && dotnet ConsoleApp3.dll

RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --shell /bin/bash -d /app app

RUN echo BQIA..AAAB | base64 -d > /app/user.keytab
RUN echo BQIA..oQ== | base64 -d > /etc/krb5.keytab
RUN echo BQIA..oQ== | base64 -d > /app/is.k01.HTTP.keytab
RUN echo BQIA..AAA= | base64 -d > /app/is.k01.kerb.keytab

COPY krb5.conf /etc/krb5.conf
COPY krb5.conf /usr/local/etc/krb5.conf
RUN ln -s /etc/gss /usr/local/etc/gss

RUN cd /app
WORKDIR /app
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

但是,我现在收到此错误:

System.Exception: An authentication exception occured (0xD0000/0x4E540016).
 ---> Interop+NetSecurityNative+GssApiException: GSSAPI operation failed with error - Unspecified GSS failure.  Minor code may provide more information (Feature not available).
   at System.Net.Security.NegotiateStreamPal.GssAcceptSecurityContext(SafeGssContextHandle& context, Byte[] buffer, Byte[]& outputBuffer, UInt32& outFlags)
   at System.Net.Security.NegotiateStreamPal.AcceptSecurityContext(SafeFreeCredentials credentialsHandle, SafeDeleteContext& securityContext, ContextFlagsPal requestedContextFlags, Byte[] incomingBlob, ChannelBinding channelBinding, Byte[]& resultBlob, ContextFlagsPal& contextFlags)
Run Code Online (Sandbox Code Playgroud)

*** 编辑现在它在这里失败:gssntlm_init_sec_context.. gssntlm_acquire_cred.. gssntlm_acquire_cred_from..

services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate(

    options =>
    {
        options.PersistKerberosCredentials = true;
        options.Events = new NegotiateEvents()
        {
            OnAuthenticated = challange =>
            {
                ..
            },
            OnChallenge = challange =>
            {
                ..
            },
            OnAuthenticationFailed = context =>
            {
                // context.SkipHandler();
                Console.WriteLine($"{DateTimeOffset.Now.ToString(czechCulture)} OnAuthenticationFailed/Scheme: {context.Scheme.Str()}, Request: {context.Request.Str()}");
                Console.WriteLine("context?.HttpContext?.Features?.Select(f=>f.Key.Name.ToString())");
                var items = context?.HttpContext?.Features?.Select(f => "- " + f.Key?.Name?.ToString());
                if (items != null)
                {
                    Console.WriteLine(string.Join("\n", items));
                }
                Console.WriteLine("context.HttpContext.Features.Get<IConnectionItemsFeature>()?.Items " + context.HttpContext.Features.Get<IConnectionItemsFeature>()?.Items?.Count);
                var items2 = context.HttpContext?.Features.Get<IConnectionItemsFeature>()?.Items?.Select(f => "- " + f.Key?.ToString() + "=" + f.Value?.ToString());
                if (items2 != null) {
                    Console.WriteLine(string.Join("\n", items2));
                }
                return Task.CompletedTask;
            }
        };
    }
);
Run Code Online (Sandbox Code Playgroud)

get_user_file_creds() 返回错误,因为我没有特定的文件设置,因为我想验证来自广告的用户

external_get_creds() 在这里失败:

try
{
    var token = "MyToken==";
    var secAssembly = typeof(AuthenticationException).Assembly;
    Console.WriteLine("var ntAuthType = secAssembly.GetType(System.Net.NTAuthentication, throwOnError: true);");
    var ntAuthType = secAssembly.GetType("System.Net.NTAuthentication", throwOnError: true);
    Console.WriteLine("var _constructor = ntAuthType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();");
    var _constructor = ntAuthType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();
    Console.WriteLine("var credential = CredentialCache.DefaultCredentials;");
    var credential = CredentialCache.DefaultCredentials;
    Console.WriteLine("var _instance = _constructor.Invoke(new object[] { true, Negotiate, credential, null, 0, null });");
    var _instance = _constructor.Invoke(new object[] { true, "Negotiate", credential, null, 0, null });

    var negoStreamPalType = secAssembly.GetType("System.Net.Security.NegotiateStreamPal", throwOnError: true);
    var _getException = negoStreamPalType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(info => info.Name.Equals("CreateExceptionFromError")).Single();


    Console.WriteLine("var _getOutgoingBlob = ntAuthType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(info => info.Name.Equals(GetOutgoingBlob) && info.GetParameters().Count() == 3).Single();");
    var _getOutgoingBlob = ntAuthType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(info => info.Name.Equals("GetOutgoingBlob") && info.GetParameters().Count() == 3).Single();
    Console.WriteLine("var decodedIncomingBlob = Convert.FromBase64String(token);;");
    var decodedIncomingBlob = Convert.FromBase64String(token);
    Console.WriteLine("var parameters = new object[] { decodedIncomingBlob, false, null };");
    var parameters = new object[] { decodedIncomingBlob, false, null };
    Console.WriteLine("var blob = (byte[])_getOutgoingBlob.Invoke(_instance, parameters);");
    var blob = (byte[])_getOutgoingBlob.Invoke(_instance, parameters);
    if (blob != null)
    {
        Console.WriteLine("var out1 = Convert.ToBase64String(blob);");
        var out1 = Convert.ToBase64String(blob);
        Console.WriteLine(out1);
    }
    else
    {
        Console.WriteLine("null blob value returned");


        var securityStatusType = secAssembly.GetType("System.Net.SecurityStatusPal", throwOnError: true);
        var _statusException = securityStatusType.GetField("Exception");
        var securityStatus = parameters[2];
        var error = (Exception)(_statusException.GetValue(securityStatus) ?? _getException.Invoke(null, new[] { securityStatus }));
        Console.WriteLine("Error:");
        Console.WriteLine(error);
        Console.WriteLine("securityStatus:");
        Console.WriteLine(securityStatus.ToString());
    }
}
catch(Exception exc)
{
    Console.WriteLine(exc.Message);
}
Run Code Online (Sandbox Code Playgroud)

external_get_creds 尝试使用 winbind 库进行身份验证,显然在凭据缓存中没有用户存在

我设法用 samba 提供的 winbind 库编译它

所以现在的问题是: 如何设置 winbind 库与 AD 通信?

*** 编辑

我曾尝试在 github 上使用 .net 5,有人告诉我 NTLM 在 .net 5 中工作。但是我得到了与 .net 3.1 相同的结果。

我尝试过的 Docker 图像:

FROM mcr.microsoft.com/dotnet/core-nightly/sdk:5.0-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y

RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user

RUN mkdir /app

RUN apt install -y mc sudo syslog-ng python3-software-properties software-properties-common packagekit git gssproxy vim apt-utils
RUN apt install -y autoconf automake libxslt-dev doxygen findutils libgettextpo-dev libtool m4 make libunistring-dev libssl-dev zlib1g-dev gettext xsltproc libxml2-utils libxml2-dev xml-core docbook-xml docbook-xsl bison libkrb5-dev
RUN systemctl enable syslog-ng
RUN mkdir /src 


#RUN cd /src && git clone https://github.com/scholtz/gss-ntlmssp.git 
RUN DEBIAN_FRONTEND=noninteractive apt install -y libwbclient-dev samba samba-dev
#RUN cat /usr/include/samba-4.0/wbclient.h

COPY gss-ntlmssp /usr/local/src/gss-ntlmssp
RUN cd /usr/local/src/gss-ntlmssp/ && autoreconf -f -i && ./configure && make && make install
RUN cp /usr/local/src/gss-ntlmssp/examples/mech.ntlmssp.conf /etc/gss/mech.d/mech.ntlmssp.conf
RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --shell /bin/bash -d /app app

RUN echo BQIAAABMA..ArHdoQ== | base64 -d > /etc/krb5.keytab

COPY krb5.conf /etc/krb5.conf
COPY smb.conf /etc/samba/smb.conf
COPY krb5.conf /usr/local/etc/krb5.conf

RUN DEBIAN_FRONTEND=noninteractive apt install -y winbind

ENV KRB5_TRACE=/dev/stdout

RUN mkdir /src2
WORKDIR /src2
RUN dotnet --list-runtimes
RUN dotnet new webapi --auth Windows 
RUN dotnet add package Microsoft.AspNetCore.Authentication.Negotiate


RUN sed -i '/services.AddControllers/i services.AddAuthentication(Microsoft.AspNetCore.Authentication.Negotiate.NegotiateDefaults.AuthenticationScheme).AddNegotiate();' Startup.cs 

RUN sed -i  '/app.UseAuthorization/i app.UseAuthentication();' Startup.cs
run echo a
RUN cat Startup.cs

RUN dotnet restore
RUN dotnet build


ENV ASPNETCORE_URLS="http://*:5002;https://*:5003"
EXPOSE 5002
EXPOSE 5003

RUN cd /app
WORKDIR /app
Run Code Online (Sandbox Code Playgroud)
docker run -it -p 5003:5003 -it registry.k01.mydomain.com/k01-devbase:latest
Run Code Online (Sandbox Code Playgroud)

在 docker 容器中:

kinit HTTP/myuser@MYDOMAIN.COM -k -t /etc/krb5.keytab
klist
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

dotnet run src2.dll
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我已将自己的调试信息放入 gssntlmssp 库中并将其放入文件

cat /tmp/gss-debug.log
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

这与我完成 .net core 3.1 的结局完全相同。

wbcCredentialCache (samba lib) 在找不到缓存凭据时失败

这是我的 krb5.conf:

[appdefaults]
    default_lifetime      = 25hrs
    krb4_convert          = false
    krb4_convert_524      = false

    ksu = {
        forwardable       = false
    }

    pam = {
        minimum_uid       = 100
        forwardable       = true
    }

    pam-afs-session = {
        minimum_uid       = 100
    }

[libdefaults]
    default_realm         = MYDOMAIN.COM

[realms]
     MYDOMAIN.COM = {
        kdc            = DC01.MYDOMAIN.COM
  

ZEv*_*EvS 7

这篇文章是误解事物运作方式的一个很好的例子。我完全不建议遵循作者在此处描述的方式(就像我所做的那样)。

相反,我建议您了解 Kerberos 身份验证、它是如何工作的以及它需要哪些设置。这篇文章很好地形象化了它。

第一的, 如果您分析来自浏览器(例如用户 Fiddler)的 http 流量,您可以在第二个请求中找到 TGS 令牌。

  • 如果它以 Negotiate 开头 TlR那么您正在通过 NTLM 进行身份验证。
  • 如果它以 Negotiate 开头,YII那么您正在通过 Kerberos 进行身份验证。

其次, 就像 David 在 ASP.NET Core 3.1 之前所说的那样,Linux 上根本不支持 NTLM。因此,如果您有TlR令牌和ntlm-gssapi机制,您将收到“未提供凭据,或者凭据不可用或无法访问”。错误。如果您有TlR令牌并使用默认 Kerberos 机制,您将收到“请求了不受支持的机制”。

接下来, 让您的应用程序正常运行的唯一方法是为Kerberos 身份验证创建 SPN 并正确生成密钥表不幸的是,这没有得到很好的记录。所以,我将在这里举一个例子,让事情更清楚。

假设你有:

  • AD域 MYDOMAIN.COM
  • 带有主机的 Web 应用程序 webapp.webservicedomain.com。这可以以 结尾mydomain.com,但在我的情况下不是。
  • Windows 机器以名称加入 AD mymachine
  • 机器账号 MYDOMAIN\mymachine

关于此处描述的说明您需要执行以下操作:

  1. 将新的 Web 服务 SPN 添加到计算机帐户:
  • setspn -S HTTP/webapp.webservicedomain.com mymachine
  • setspn -S HTTP/webapp@MYDOMAIN.COM mymachine
  1. 使用ktpass生成keytab文件
  • ktpass -princ HTTP/webapp.webservicedomain.com@MYDOMAIN.COM -pass myKeyTabFilePassword -mapuser MYDOMAIN\mymachine$ -pType KRB5_NT_PRINCIPAL -out c:\temp\mymachine.HTTP.keytab -crypto AES256-SHA1*.

*确保在 ADMYDOMAIN\mymachineAES256-SHA1允许。

最后, 在完成上述所有工作并将应用程序部署到带有 keytab 的 Linux 容器后,集成 Windows 身份验证应该可以正常工作。我的实验表明,您不仅可以在名为“mymachine”的主机上随时随地使用 keytab。

  • SPN 确实是 Kerberos 的成败。需要注意的是,客户端(浏览器)决定 SPN,服务提供商服务器和域必须遵守这一点。就我而言,我被烧毁了,因为我在开发过程中在非标准端口上运行服务,所以我尝试将 SPN 注册为 HTTP/[主机名]:6000。浏览器忽略端口部分,并向域请求 SPN“HTTP/[hostname_without_port]”的票证。当域找不到它时,静默后备是 NTLM(.NET 中不受支持)。 (3认同)
  • 我删除了 SPN 并重试,然后它们就起作用了。所以对其他人来说:我很确定 SPN 是它使用 krb 而不是 ntlm 的原因,并且您必须使用 setspn 命令而不是 adsiedit。 (2认同)

Dav*_*SFT 3

在 dotnet 运行时 git 中,他们告诉我们需要 gss-ntlmssp 才能工作,即使在 aspnet 核心文档中没有提到它。

“gss-ntlmssp”包是一个用于支持 GSS-API 的 NTLM 协议的插件。它支持原始 NTLM 协议以及在使用“协商”(SPNEGO 协议)时将 NTLM 用作从 Kerberos 到 NTLM 的后备。参考:https://learn.microsoft.com/en-us/openspecs/windows_protocols/MS-SPNG/f377a379-c24f-4a0f-a3eb-0d835389e28a

通过阅读上面的讨论和您发布的图像,该应用程序似乎正在尝试实际使用 NTLM 而不是 Kerberos。您可以看出,因为 based64 编码的令牌以“T”而不是“Y”开头。

ASP.NET Core 服务器 (Kestrel) 根本不支持 Linux 上的 NTLM 服务器端。它仅提供将“Www-Authenticate: Negotiate”发送回客户端。通常这意味着将使用 Kerberos。Negotiate 可以回退到使用 NTLM。但是,除了尚未发布的 .NET 5 之外,这在 ASP.NET Core 中不起作用。

您是否期望您的应用程序回退到 NTLM?如果没有,那么 Kerberos 环境可能尚未完全设置。这可能是由多种问题引起的,包括 SPN 和 Linux keytab 文件不正确。这也可能是由于客户端尝试使用不属于 Kerberos 领域的用户名/密码引起的。

这里讨论这个问题:https ://github.com/dotnet/aspnetcore/issues/19397

我建议在 aspnet core repo 问题讨论中继续对话。