如何在控制器方法中使 JWT 令牌授权可选

How to make JWT token authorization optional in controller methods

我在 ASP.NET Core 2 Web 应用程序中使用 JWT 令牌

如果 JWT 令牌失败,我仍然希望控制器方法被命中,但 ASP.NET Identity User 对象将只是 null。目前,如果身份验证失败,则不会进入控制器方法,因此我无法在方法中应用逻辑来处理我想作为来宾而不是阻止他们处理的未经过身份验证的用户。

我的代码:

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {

        services.AddAuthentication()
            .AddJwtBearer(cfg =>
            {
                cfg.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidIssuer = _config["Tokens:Issuer"],
                    ValidAudience = _config["Tokens:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]))
                };

            });

当用户登录时

   private IActionResult CreateToken(ApplicationUser user, IList<string> roles)
    {
        var claims = new List<Claim>
        {
          new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
          new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
          new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
        };



        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]));

        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
          _config["Tokens:Issuer"],
          _config["Tokens:Audience"],
          claims.ToArray(),
         expires: DateTime.Now.AddMinutes(60),
          signingCredentials: creds);

        var results = new
        {
            token = new JwtSecurityTokenHandler().WriteToken(token),
            expiration = token.ValidTo,
        };

        return Created("", results);

我确保在对各种 API 调用进行身份验证后传递 JWT 令牌。

在我的控制器中,我使用了授权属性

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
 public class MyController : Controller
{

这允许我使用以下代码为各种 API 调用捕获登录用户

 var loggedInUser = User.Identity.Name;

如果我删除授权属性,那么 User.Identity.Name 将始终为 null,即使用户已通过身份验证也是如此。

如果令牌无效,如何使用授权属性但仍允许输入控制器方法?我想对要输入的授权用户和非授权用户使用相同的方法。然后,我将使用 User.Identity.Name 来确定他们是否未通过身份验证,并且在他们的方法中有来宾用户逻辑。

实际上比您想象的要容易。您可以同时使用 AuthorizeAllowAnonymous,像这样:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[AllowAnonymous]
public class MyController : Controller

如果授权成功,您将拥有一个经过身份验证的 User (User.Identity.IsAuthenticated = true),否则,您将拥有一个匿名 User.

通过稍微更新 ASP.NET 核心,除了配置您的令牌指南之外,您还可以通过添加以下内容使您的控制器需要 Bearer Token 身份验证:

Startup.cs

  public void ConfigureServices(IServiceCollection services)
  {
      services.AddJwtSecurity(
                signingConfigurations, tokenConfigurations);
  }

请记住,如果您想一次阻止整个控制器,只需将其添加到授权的顶部即可 class。

namespace <name_controller>
{    
    [Produces("application/json")]
    [Route("api/v1/[controller]")]
    [ApiController]
    [RequireHttps]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public class clientesController : Controller
    {
    }
}

我不确定这何时更改,但我的应用程序在 ASP.NET Core 3.1 上并且没有我的 actions/endpoints 指定我需要授权,身份验证中间件仍然提供我需要的信息ClaimsPrincipal 提供有效令牌时,未指定令牌时为空白主体。