【问题标题】:.NET Core Web API key.NET Core Web API 密钥
【发布时间】: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] 属性? (密钥存储在数据库中。)

【问题讨论】:

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

标签: c# asp.net-core asp.net-identity


【解决方案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。

【讨论】:

    猜你喜欢
    • 2020-11-16
    • 2018-05-08
    • 2018-12-20
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多