带有自定义API密钥中间件的.Net Core JWT身份验证 [英] .Net Core JWT Authentication with custom API Key Middleware
问题描述
我有一个使用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屋!