.Net Core Web Api Key

Jam*_*ees 21 c# asp.net-identity asp.net-core

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

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

我不确定如何做到这一点,因为身份验证部分似乎是一个黑盒子(使用Aspnet身份).

以下是我的一些身份验证设置代码

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,

    });
 //....
}
Run Code Online (Sandbox Code Playgroud)

上述代码[Authorized]在控制器上具有属性并检查角色等时起作用.

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

谢谢

Jam*_*ees 20

这就是我最后所做的:

 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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

自从我回答了原始问题后,这已经发生了很大的变化(答案仍然有效).但你可以在这里看到实现:https://github.com/tidusjar/Ombi/blob/master/src/Ombi/ApiKeyMiddlewear.cs