【问题标题】:How to use Windows authentication on ASP.NET Core subpath only?如何仅在 ASP.NET Core 子路径上使用 Windows 身份验证?
【发布时间】:2021-08-25 04:39:02
【问题描述】:

我正在尝试仅在我的 ASP.NET Core MVC 应用程序中对子路由配置 Windows 身份验证。

我的问题是当我添加时

services.AddAuthentication().AddNegotiate()

我收到一个错误

协商身份验证处理程序不能在直接支持 Windows 身份验证的服务器上使用。

这导致我添加 web.config 作为文档解释:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <location path="." inheritInChildApplications="false">
        <system.webServer>
            <security>
                <authentication>
                    <anonymousAuthentication enabled="false" />
                    <windowsAuthentication enabled="true" />
                </authentication>
            </security>
        </system.webServer>
    </location>
</configuration>

并且错误消失了。但是,现在每个请求都会弹出 Windows 身份验证。

我尝试将位置路径更改为.testendpoint,但这会在基本路径中引发原始错误。

那么有可能吗?我该如何做到这一点?只有/testendpoint 会要求 Windows 身份验证,而应用程序的其余部分将与我在 ASP.NET Core 应用程序中配置的任何其他身份验证一起使用?

【问题讨论】:

  • 从几周前通过类似研究收集到的非常浅薄的知识来看(我面临着类似的情况,如果协商/NTLM 失败,应用程序应该回退到 cookie 身份验证)我不认为这是可能的,因为 Windows 身份验证发生在服务器而不是应用程序级别。但我很乐意被证明是错误的。
  • 我正在取得进展,annonymousauthentication=true 还允许服务器在服务器级别失败时传递并使用 cookie,并形成 aspnet 核心我可以挑战协商身份验证架构并触发 Windows 身份验证它带有 ntlm 的索赔主体。所以我基本上是在创建一个登录路由,根据我从 ntlm 获得的信息来挑战和登录应用程序 cookie
  • 我自己回来篡改它,@pfx's 绝对是这里的正确答案。只要启用了“匿名”和“Windows”身份验证(在 IISExpress 上使用自定义 Cookie 和协商身份验证进行测试),它就可以像 IISExpress 上的魅力一样工作。从中间件或类似的内部调用方案挑战的手动方法如下所示。

标签: asp.net-core .net-core windows-authentication


【解决方案1】:

为了通过 Windows 身份验证保护某个页面/操作方法,请在操作方法Authorize 属性中指定相应的身份验证方案。

[Authorize(AuthenticationSchemes = IISServerDefaults.AuthenticationScheme)]
public IActionResult UsingWindowsAuthentication()

确保在您的网站上启用Windows authentication
为了使用其他身份验证方案,例如“个人账户”,匿名认证也开启了。

不得使用 Windows 身份验证的控制器和/或操作方法已指定默认方案。
例如,对于使用开箱即用的“个人帐户”身份验证类型作为默认身份验证方法的ASP.NET Core MVC 项目,即Identity.Application

[Authorize(AuthenticationSchemes = "Identity.Application")]
public IActionResult Index()

请参阅documentation,了解如何设置和配置多个身份验证方案。

【讨论】:

  • 这些方案之间是否有可能形成分离?例如,根据特定条件尝试 Windows 身份验证,如果在没有提示的情况下无法完成,则启动第二个方案的质询?
  • @Beltway 该链接文章显示 AuthorizeAttribute 可以有多个方案,并且都有机会处理请求。我假设这些按此顺序运行。任何其他规则都可以通过自定义 AuthorizAttribute 或策略要求设置。
  • policy.AuthenticationSchemes.Add({schemeDefaults}.AuthenticationScheme); 正是我正在寻找的。我之前省略了这一点,因为它似乎没有执行正确的方案,这仅仅是因为 Edge 没有正确删除 cookie 并显示虚假声明。感谢您指点我回到那里,这很有帮助!
【解决方案2】:

使用端点路由的另一种方式:

我们有一个应用程序架构,将在整个应用程序中使用,称为 eavfw。

在此处使用名为 login/ntlm 的自定义端点,元数据为 new AuthorizeAttribute(NegotiateDefaults.AuthenticationScheme),它只允许由有效的 Windows 身份验证用户访问。

然后,我们在数据库中使用其 AD 用户名创建用户。

    endpoints.MapGet("/.auth/login/ntlm", async httpcontext =>
    {
        var loggger = httpcontext.RequestServices.GetRequiredService<ILogger<Startup>>();
        var windowsAuth = await httpcontext.AuthenticateAsync(NegotiateDefaults.AuthenticationScheme);
        
        if (!windowsAuth.Succeeded)
        {
            loggger.LogWarning("Not authenticated: Challening"); 
        }
        if (windowsAuth.Succeeded)
        {
            loggger.LogWarning("Authenticated");
           
            var name = string.Join("\\", windowsAuth.Principal.Claims.FirstOrDefault(c => c.Type.EndsWith("name")).Value.Split("\\").Skip(1));

            var context = httpcontext.RequestServices.GetRequiredService<DynamicContext>();
            var users = context.Set<SystemUser>();
            var user = await context.Set<SystemUser>().Where(c => c.PrincipalName == name).FirstOrDefaultAsync();
            if (user == null)
            {
                user = new SystemUser
                {
                    PrincipalName = name,
                    Name = name,
                    // Email = email,
                };
                await users.AddAsync(user);
                await context.SaveChangesAsync();
            }
             
            var principal = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] {                                  
                       new Claim(Claims.Subject,user.Id.ToString())
                    }, "ntlm"))
            {

            };

            await httpcontext.SignInAsync("ntlm",
                 principal, new AuthenticationProperties(
                            new Dictionary<string, string>
                            {
                                ["schema"] = "ntlm"
                            }));

            httpcontext.Response.Redirect("/account/login/callback");
        }
      

    }).WithMetadata(new AuthorizeAttribute(NegotiateDefaults.AuthenticationScheme));

使用辅助身份验证 cookie,我们现在可以使我们的应用程序的特定区域需要 Windows 身份验证,它可以简单地依赖 Authorize("ntlm"),因为它会自动转发身份验证调用以检查是否已经登录,并且它作为上述端点中的登录调用的一部分,实际上在它重定向到一般帐户回调页面之前登录 eavfw.external,该页面将在从 eavfw.external cookie 登录 eavfw 之前进行一些最终验证

            services.AddAuthentication().AddCookie("ntlm", o => {
                o.LoginPath = "/.auth/login/ntlm";
                o.ForwardSignIn = "eavfw.external";
                o.ForwardAuthenticate = "eavfw";
            });

因此,根据您的应用程序的 MVC 框架的繁重程度,有几种方法可以扩展和使用 auth 核心中的身份验证系统。

【讨论】:

  • 超级有用且功能齐全,可进行一些项目更改。这对我帮助很大。我正在使用 websockets,所以整个 MVC 的东西甚至不存在。能够使用中间件来解决这个问题正是我所需要的,并且在任何地方似乎都没有记录。谢谢!
猜你喜欢
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-30
相关资源
最近更新 更多