2017-09-19 60 views
5

我有一个.Net核心2.0应用程序,它使用JWT令牌来授权用户。 这一切工作正常,但我想有某种API键机制,以允许其他应用程序集成,但我似乎无法得到这与当前身份验证的工作。.Net核心JWT身份验证与自定义API密钥中间件

代码:

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函数时,认为这不工作,我收到以下错误日志:

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标头。

我该如何才能够提供一个ApiKey标头,并且当没有ApiKey标头,然后回退到需要一个JWT标记?

+0

是否使用Asp.net的身份? –

+0

@AramKocharyan是 –

+0

你是否在'Roles'属性中使用'Authorize'属性?像'[Authorize(Roles =“foo”)]' –

回答

3

Claim("role", "Admin")应用到GenericPrincipal不会影响任何内容,因为GenericPrincipal与角色声明无关。所以,如果你想管理角色适用于GenericPrincipal,你需要将其添加在构造函数中的参数:

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