.NET Core Web API 密钥

Posted

技术标签:

【中文标题】.NET Core Web API 密钥【英文标题】:.NET Core Web API key 【发布时间】:2018-01-29 14:24:25 【问题描述】:

我正在开发一个应用程序,用户可以通过用户名和密码进行身份验证,我们提供了一个 JWT 令牌,然后在服务器上进行验证。

我想补充的一件事是能够拥有一个特殊的 API 密钥 (guid),用户可以在与此应用程序集成时使用它,而不是使用用户名和密码。

我不确定如何执行此操作,因为身份验证部分似乎有点像黑匣子(使用 Aspnet Identity)。

这是我的一些身份验证设置代码。

Startup.cs

public void ConfigureServices(IServiceCollection services)

    // Add framework services.
    services.AddDbContext<OmbiContext>(options =>
        options.UseSqlite("Data Source=Ombi.db"));

    services.AddIdentity<OmbiUser, IdentityRole>()
        .AddEntityFrameworkStores<OmbiContext>()
        .AddDefaultTokenProviders();

    services.Configure<IdentityOptions>(options =>
    
        options.Password.RequireDigit = false;
        options.Password.RequiredLength = 1;
        options.Password.RequireLowercase = false;
        options.Password.RequireNonAlphanumeric = false;
        options.Password.RequireUppercase = false;
    );


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IMemoryCache cache)

    var tokenOptions = (IOptions<TokenAuthentication>)app.ApplicationServices.GetService(
        typeof(IOptions<TokenAuthentication>));

    var ctx = (IOmbiContext)app.ApplicationServices.GetService(typeof(IOmbiContext));

    var tokenValidationParameters = new TokenValidationParameters
    

        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.Value.SecretKey)),

        RequireExpirationTime = true,
        ValidateLifetime = true,
        ValidAudience = "Ombi",
        ValidIssuer = "Ombi",
        ClockSkew = TimeSpan.Zero
    ;

    app.UseJwtBearerAuthentication(new JwtBearerOptions()
    
        Audience = "Ombi",
        AutomaticAuthenticate = true,
        TokenValidationParameters =  tokenValidationParameters,

    );
 //....

上述代码在控制器上具有[Authorized] 属性并检查角色等时有效。

任何人都知道如何在包含此特殊 API 密钥的所有请求上传递某种 Api-Key 标头以传递 [Authorized] 属性? (密钥存储在数据库中。)

【问题讨论】:

***.com/questions/31464359/… @stuartd 不确定上述是否适用,查看它我需要为每个控制器定义该策略,在这种情况下,API Key 标头将始终需要存在。基本上我正在寻找一种方法来向授权我的服务器提供秘密。 您在请求中提供带有授权标头的不记名令牌。并且根据授权服务器所在的位置,您需要对其进行验证。 IE。在 azure AD 中,如果您只想针对服务器中的硬编码密钥进行验证,您可以在 appregistration 下添加一个 api,您可以通过自己的声明验证器进行验证,检查 AuthorizationHandler 类 【参考方案1】:

这就是我最后所做的:

 public static void ApiKeyMiddlewear(this 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();
                    await ValidateApiKey(serviceProvider, context, next, headerKey);
                
                else if (context.Request.Query.ContainsKey("apikey"))
                
                    if (context.Request.Query.TryGetValue("apikey", out var queryKey))
                    
                        await ValidateApiKey(serviceProvider, context, next, queryKey);
                    
                
                else
                
                    await next();
                
            
            else
            
                await next();
            
        );
    

    private static async Task ValidateApiKey(IServiceProvider serviceProvider, HttpContext context, Func<Task> next, string key)
    
        // validate it here
        var valid = false;
        if (!valid)
        
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            await context.Response.WriteAsync("Invalid API Key");
        
        else
        
            var identity = new GenericIdentity("API");
            var principal = new GenericPrincipal(identity, new[]  "Admin", "ApiUser" );
            context.User = principal;
            await next();
        
    

自从我回答了原始问题(答案仍然有效)以来,情况发生了很大变化。但你可以在这里阅读:https://tidusjar.github.io/2019/03/25/net-core-jwt-api-key/

【讨论】:

您能否详细说明您想在 ValidateApiKey 的 else 主体上实现什么?我担心的是验证 ApiKey,但随后在具有属性 [Authorize] 的操作上被拒绝。您如何处理中间件以跳过该属性? 基本上await context.Response.WriteAsync("Invalid API Key"); 然后`await next.Invoke(context);`。你可以在这里看到这个:github.com/tidusjar/Ombi/blob/master/src/Ombi/… 嘿@JamieRees 感谢这个解决方案,它帮助了我很多!您如何看待检查 ApiKey,我们查找 client_id 并检查 client_id 是否有权访问受保护的范围(如 Api 资源)?【参考方案2】:

在此链接上有一篇关于在标头请求中使用 api 键的好文章: http://www.mithunvp.com/write-custom-asp-net-core-middleware-web-api/

总而言之,在 ASP.NET Core 中,您可以使用中间件来控制 http 管道配置。中间件有效地替代了早期版本的 asp.net MVC 中使用的 HttpHandlers。

【讨论】:

以上是关于.NET Core Web API 密钥的主要内容,如果未能解决你的问题,请参考以下文章