c# - 使用自定义 API key 中间件的 .Net Core JWT 身份验证

标签 c# .net asp.net-core asp.net-identity jwt

我有一个使用 JWT token 授权用户的 .Net Core 2.0 应用程序。 这一切都很好,但我想要某种 API key 机制来允许其他应用程序集成,但我似乎无法让它与当前身份验证一起使用。

代码:

Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,
            IMemoryCache cache, IServiceProvider serviceProvider)
{
    app.UseAuthentication();

    ApiKeyMiddlewear(app, serviceProvider);

    app.UseMvc(routes =>
    { 
        routes.MapRoute(
               name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
    }
}


    private static void ApiKeyMiddlewear(IApplicationBuilder app, IServiceProvider serviceProvider)
    {
        app.Use(async (context, next) =>
        {
            if (context.Request.Path.StartsWithSegments(new PathString("/api")))
            {
                // Let's check if this is an API Call
                if (context.Request.Headers["ApiKey"].Any())
                {
                    // validate the supplied API key
                    // Validate it
                    var headerKey = context.Request.Headers["ApiKey"].FirstOrDefault();
                    var settingsProvider = serviceProvider.GetService<ISettingsService<OmbiSettings>>();
                    var ombiSettings = settingsProvider.GetSettings();
                    var valid = ombiSettings.ApiKey.Equals(headerKey, StringComparison.CurrentCultureIgnoreCase);
                    if (!valid)
                    {
                        context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
                        await context.Response.WriteAsync("Invalid API Key");
                    }
                    else
                    {
                        var identity = new GenericIdentity("API");
                        identity.AddClaim(new System.Security.Claims.Claim("Origin", "Api"));
                        identity.AddClaim(new System.Security.Claims.Claim("role", "Admin"));

                        var principal = new GenericPrincipal(identity, new[] {"ApiUser"});
                        context.User = principal;
                        await next();
                    }
                }
                else
                {
                    await next();
                }
            }
            else
            {
                await next();
            }
        });
    }
}

所以在上面的代码中,您可以看到我正在拦截提供名为 ApiKey 的 header 的 HTTP 请求,然后将其验证为我存储的内容。这部分一切正常,但是当使用 Authorize 属性调用 API 方法时,这不起作用,我收到以下错误日志:

2017-09-19 08:15:17.280 +01:00 [Information] Request starting HTTP/1.1 POST http://localhost:52038/api/v1/Identity/ application/json 372
2017-09-19 08:15:21.967 +01:00 [Information] Authorization failed for user: "API".
2017-09-19 08:15:21.976 +01:00 [Information] Authorization failed for the request at filter '"Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter"'.
2017-09-19 08:15:21.981 +01:00 [Information] Executing ForbidResult with authentication schemes ([]).
2017-09-19 08:15:21.991 +01:00 [Information] AuthenticationScheme: "Bearer" was forbidden.
2017-09-19 08:15:21.996 +01:00 [Information] Executed action "Ombi.Controllers.IdentityController.CreateUser (Ombi)" in 38.8268ms
2017-09-19 08:15:22.004 +01:00 [Information] Request finished in 4723.032ms 403 

现在我猜这与只提供 ApiKey header 而不是带有正确 JWT token 的 Authorization header 的请求有关。

我如何才能只提供 ApiKey header ,并且在没有 ApiKey header 时退回到需要 JWT token ?

最佳答案

Claim("role", "Admin") 应用于 GenericPrincipal 不会有任何影响,因为 GenericPrincipal 与 Role 无关 claim 。所以如果你想给 GenericPrincipal 应用 admin 角色,你需要在构造函数参数中添加它:

 var principal = new GenericPrincipal(identity, new[] {"Admin","ApiUser"});
 context.User = principal;

关于c# - 使用自定义 API key 中间件的 .Net Core JWT 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46294399/

相关文章:

c# - ASP.NET Core - 提供静态文件

c# - 使用 Linq 关联防止空异常

c# - Windows 应用程序中的异常处理 C#

c# - 如何确定是否正在处理 .NET 异常?

.net - 队列 <T> 与列表 <T>

c# - Asp.net Core MVC - 在应用程序关闭期间获取依赖项

c# - 在 ASP.NET Core 中到达 Controller 之前拦截不良请求

c# - Azure Function 中的复杂对象应用设置

c# 根据当前日期获取开始日期和最后日期

c# - Obsolete 属性是否仅在编译时检查?