如何将 Windows 身份验证和 JWT 与 .Net Core 2.1 结合使用

Jen*_*nan 6 authentication windows-authentication jwt asp.net-core

我尝试将 Windows 身份验证和 JWT 与 .NET Core 2.1 一起使用。

我有以下身份验证的启动设置:

services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = IISDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,

                    ValidIssuer = "Test",
                    ValidAudience = "Test",
                    IssuerSigningKey = JwtSecurityKey.Create("677efa87-aa4d-42d6-adc8-9f866e5f75f7")
                };

                options.Events = new JwtBearerEvents()
                {
                    OnAuthenticationFailed = OnAuthenticationFailed
                };
            });
Run Code Online (Sandbox Code Playgroud)

IIS 设置:

"iisSettings": {
    "windowsAuthentication": true, 
    "anonymousAuthentication": true, 
    ..
  }
Run Code Online (Sandbox Code Playgroud)

我尝试使用以下代码片段来创建带有 Windows 身份验证的 JWT 令牌:

[Route("api/[controller]")]
    [ApiController]
    [Authorize(AuthenticationSchemes = "Windows")]
    public class AuthController : ControllerBase
    {
        [HttpPost("token")]
        public IActionResult Token()
        {
            //Setup claims
            var claims = new[]
            {
                new Claim(ClaimTypes.Name, User.Identity.Name),
                //Add additional claims
            };

            //Read signing symmetric key
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("677efa87-aa4d-42d6-adc8-9f866e5f75f7"));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //Create a token
            var token = new JwtSecurityToken(
                issuer: "Test",
                audience: "Test",
                claims: claims,
                expires: DateTime.Now.AddMinutes(30),
                signingCredentials: creds);

            //Return signed JWT token
            return Ok(new
            {
                token = new JwtSecurityTokenHandler().WriteToken(token)
            });
        }
    }
Run Code Online (Sandbox Code Playgroud)

在另一个控制器中,我只需要使用 JWT 身份验证:

[Route("api/[controller]")]
    [ApiController]
    [Authorize(AuthenticationSchemes = "Bearer")]
    public class ProductController : ControllerBase
    {
        [HttpGet]
        public IActionResult Get()
        {
            var userName = User.Identity.Name;

            var claims = User.Claims.Select(x => new { x.Type, x.Value });

            return Ok(new { userName, claims });
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果 JWT 令牌已过期,那么我正确地收到了响应代码,401但我仍然在浏览器中看到用于放置凭据的对话框。

当我想创建 JWT 令牌并禁用负责显示带有凭据的浏览器对话框的响应时,如何仅为一部分配置 Windows 身份验证?如何正确组合这些东西?

Tod*_*ton 7

我处理这个问题的方法是创建两个不同的 Web 应用程序:一个用于 Windows 身份验证,另一个使用 JWT 令牌身份验证。

Windows 身份验证 Web 应用程序将非常小并且只做一件事。在端点通过 Windows 身份验证对用户进行身份验证并返回 JWT 令牌。

然后,该令牌可用于主应用程序。只要您的签名密钥和受众相同,是否在不同的 Web 应用程序上创建令牌都没有关系。

您无需费力尝试同时处理两者。


小智 6

要同时使用 Windows 和 JWT 承载身份验证 - 默认情况下,Windows 身份验证会应用于所有页面,并且它会覆盖 JWT 承载身份验证的功能。将两者合并为一个 应用程序:-

  1. 在提供程序上应用 Windows 身份验证,该提供程序用于使用 [AllowAnonymous] 标签生成 JWt Bearer 的令牌,默认情况下使用 Windows 身份验证
  2. 使用 [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] 在应用程序的其余页面上应用 Jwt Bearer 身份验证

因此,在上面的情况下,我们使用 Windows 身份验证来生成 JWT 令牌,并使用该 JWT 令牌对应用程序中的其余页面进行身份验证。

对于测试场景,您可以尝试使用 NTLM(Windows 身份验证)作为令牌生成控制器的邮递员,并使用具有 JWTAuthentication 的页面的 BearerToken


wxm*_*146 5

以下是我在 .net 5 中如何在 Web api 上使用 Windows 身份验证和 Jwt。我首先让 Windows 身份验证获取身份名称,然后检查数据库表以获取角色等的授权,然后返回 jwt 令牌。客户端网站使用 jwt 令牌访问 jwt 受保护的资源。

  1. 调试时在启动设置中启用匿名和 Windows 身份验证。如果部署在服务器上,则在 iis 中。

  2. 如果您想通过 Kestrel 进行调试,在撰写本文时,在启动时,不要使用 services.AddAuthentication(IISDefaults.AuthenticationScheme);
    ,而是使用

     services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在启动配置服务中设置标准以添加 jwt 身份验证。在配置功能中,添加身份验证。

  4. 装饰你想要使用 Windows 身份验证的函数:

    [Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)]
    [Route("GetToken")]
    [HttpGet]
    public IActionResult GetToken() 
    {}
Run Code Online (Sandbox Code Playgroud)
  1. 装饰您想要使用 jwt 令牌的控制器:
    [Authorize(AuthenticationSchemes =JwtBearerDefaults.AuthenticationScheme)]
    [ApiController]
    [Route("[controller]")]
    public class ReportController : ControllerBase
    {
    }
Run Code Online (Sandbox Code Playgroud)

就这样。

  • 这不提供在未经身份验证的请求发送到 JWT 端点时隐藏浏览器身份验证对话框的解决方案。 (2认同)

Tod*_*ton 0

这个答案可能有帮助:/sf/answers/3573855771/

您需要确保在尝试使用 Windows 身份验证时未设置 Authorization: Bearer HTTP 标头。这里的关键点是“Windows Auth”实际上是如何工作的。例如,让我们看看它如何与浏览器一起工作。