.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 密钥的主要内容,如果未能解决你的问题,请参考以下文章

.Net Core 自定义身份验证使用 API 密钥和 Identity Server 4

.Net Core JWT 身份验证与自定义 API 密钥中间件

根据 ASP.NET Core 请求标头中提供的 API 密钥授权用户

如何在 ASP .NET Core Web 应用程序中向 apsettings.js 添加“密钥”及其“名称”

响应 JWT 错误的 Authentication Asp.Net Core Web Api

使用 .NET Core 中的公共安全密钥配置 JWT Bearer 令牌验证