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

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

问题描述

我有一个使用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;

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

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