如何对 ASP.NET WebApi 的每个请求应用自定义验证到 JWT 令牌?

Posted

技术标签:

【中文标题】如何对 ASP.NET WebApi 的每个请求应用自定义验证到 JWT 令牌?【英文标题】:How to apply custom validation to JWT token on each request for ASP.NET WebApi? 【发布时间】:2016-06-05 19:53:09 【问题描述】:

是否可以在使用不记名令牌对 Web api 调用进行身份验证时为每个请求添加自定义验证?

我正在使用以下配置,并且应用程序已经正确验证了 JWT 令牌。

app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions

    AuthenticationType = "jwt",
    TokenEndpointPath = new PathString("/api/token"),
    AccessTokenFormat = new CustomJwtFormat(),
    Provider = new CustomOAuthProvider(),
);

app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions

    AllowedAudiences = new[]  "all" ,
    IssuerSecurityTokenProviders = new[]  new SymmetricKeyIssuerSecurityTokenProvider(Config.JWT_Issuer, Config.JWT_Key) ,,

);

现在,由于令牌设置为永不过期,我想为每个使用不记名令牌发出的请求添加一个额外的自定义验证步骤,这样我就可以验证每个请求的一些额外信息,并在需要时拒绝访问。

为每个请求添加此验证的正确位置在哪里?

【问题讨论】:

嗨 Natan,您是如何将令牌设置为永不过期的?我使用的是 linux 到期日期,它在 2038 年 1 月之后有限制 【参考方案1】:

添加额外的逻辑来验证或验证传入的令牌:

1) 使用身份验证提供程序

    编写自定义提供程序继承自OAuthBearerAuthenticationProvider 或实现IOAuthBearerAuthenticationProvider

    在您的自定义身份验证提供程序中,覆盖/实现 ValidateIdentity(...) 和/或 RequestToken(...) 以检查每个请求的传入令牌

    通过将自定义提供程序分配给JwtBearerAuthenticationOptions.Provider 属性来使用它

例子:

app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions

    // ... other properties here
    Provider = new MyCustomTokenAuthenticationProvider()
    // ... other properties here
);

2) 使用令牌处理程序

    编写一个自定义令牌处理程序,继承自JwtSecurityTokenHandler

    覆盖您想要扩展的任何相关方法(有很多!)

    通过将自定义令牌处理程序分配给 JwtBearerAuthenticationOptions.TokenHandler 属性来使用它

例子:

app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions

    // ... other properties here
    TokenHandler = new MyCustomTokenHandler()
    // ... other properties here
);

【讨论】:

很棒的答案谢谢!似乎缺少这方面的文档,使用方法 2),您将如何添加/修改声明? 相反,您将如何处理方法 1 的令牌验证? 我不确定第一个解决方案,但至于第二个解决方案,由于JwtBearerOptions 的更改,这将不再有效。似乎最好的方法是实现自己的JwtBearerEvents。我将尝试实现一个解决方案(使用内存中的撤销后验证)并在我能解决的情况下发布一个解决方案。 @CarrieKendall ,上述任何解决方案都适用于新的 JwtBearerOption,您是否知道如何使用它实现自定义验证。如果您能分享您的解决方案,我将不胜感激。 未来读者警告:'JwtBearerAppBuilderExtensions.UseJwtBearerAuthentication(IApplicationBuilder, JwtBearerOptions)' 已过时:'参见go.microsoft.com/fwlink/?linkid=845470'github.com/aspnet/AspNetCore/issues/2007【参考方案2】:

在 .Net Core 上,您可以将其添加到 JwtBearerOptions

options.Events = new JwtBearerEvents

    OnTokenValidated = AdditionalValidation
;

您的验证函数可能如下所示:

private static Task AdditionalValidation(TokenValidatedContext context)

    if ( /* any validation */ ) 
    
        context.Fail("Failed additional validation");
    

    return Task.CompletedTask;

好消息是context 将包含您所需的一切,JWT 令牌、HttpContextClaimsPrincipal 等。

【讨论】:

这个答案对我有用。以下是我用来获取 AdditionalValidation 方法中的声明(本例中为 SID)的几个语句: if (context.SecurityToken is JwtSecurityToken accessToken) if (context.Principal.Identity is ClaimsIdentity claim) var sid = claim. FindFirst(ClaimTypes.Sid​​).Value;【参考方案3】:

我想说的最好的方法是编写自定义属性。您需要继承AuthorizeAttribute 类并覆盖AuthorizeCore 方法,在那里您可以添加自定义验证。

完成后,只需用它装饰您的控制器或方法。

https://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.118).aspx

实现示例:

public class MyCustomAttribute : AuthorizeAttribute

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    
        // your validation here
    

使用示例:

[MyCustom]
public ActionResult MyAction()

    return View();

【讨论】:

以上是关于如何对 ASP.NET WebApi 的每个请求应用自定义验证到 JWT 令牌?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 asp.net 核心 webapi 控制器中读取请求正文?

ASP.NET WebApi 对 ValidateClientAuthentication 上的 OPTIONS 的 400 错误请求,即使在 context.Validated() 上也是如此

如何在使用 JWT 的 asp.net 核心 web 应用和 web api 中使用谷歌身份验证

ASP.NET WebApi 从入门到"放弃"系列---WebApi 请求路由

对 Web api 的 ASP.NET Core 应用程序 http 客户端请求

ASP.NET WebApi实现请求频率限制