.Net Core JWT 身份验证与自定义 API 密钥中间件 [英] .Net Core JWT Authentication with custom API Key Middleware

查看:24
本文介绍了.Net Core JWT 身份验证与自定义 API 密钥中间件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a .Net Core 2.0 application that uses JWT tokens to authorize the user. This all works fine but I want to have some sort of API Key mechanism to allow other applications to integrate but I cannot seem to get this to work with the current authentication.

代码:

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 的标头的 HTTP 请求,然后将其验证为我存储的内容.这部分一切正常,但是当使用 Authorize 属性调用 API 方法时,这不起作用,我得到以下错误日志:

So in the code above you can see that I am intercepting the HTTP requests that provide a header called ApiKey and then validate it to what I have stored. This part all works but when calling an API Method with the Authorize attribute this does not work and I get the following error logs:

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 标头而不是带有正确 JWT 令牌的 Authorization 标头的请求有关.

Now I'm guessing this is to do with the request only supplying a ApiKey header and not a Authorization header with a correct JWT token.

我怎样才能只提供 ApiKey 标头,当没有 ApiKey 标头时回退到需要 JWT 令牌?

How am I able to only supply a ApiKey header and when there is no ApiKey header then fallback to requiring a JWT token?

推荐答案

应用 Claim("role", "Admin")GenericPrincipal 不会有任何影响,因为GenericPrincipal 与角色声明无关.所以如果你想为 GenericPrincipal 应用管理员角色,你需要在构造函数参数中添加它:

Applying Claim("role", "Admin") to GenericPrincipal will not affect anything, because GenericPrincipal have nothing to do with Role Claims. So if you want to apply admin role to GenericPrincipal, you need to add it in constructor parameter:

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

这篇关于.Net Core JWT 身份验证与自定义 API 密钥中间件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆