繁体   English   中英

如何在ASP Net Core中授权Web API控制器

[英]How do you Authorize a Web API Controller in ASP Net Core

我已经在C#ASP Net Core中为后端创建了API。 我正在尝试找到一种授权路线的方法,以便它将在URL中使用API​​密钥,例如“ https://mywebsite.com/api/data/first?key=VX4HCOjtMQ6ZF978a245oLw00SfK0ahm ”以对路线进行身份验证,并用JSON呈现数据。

我知道在ASP NET Core身份中,有一种方法可以对路由进行身份验证,但这需要用户先登录。 如何使用API​​密钥保护我的API路由?

您尝试执行的操作不会保护网络api。 我建议您研究OAuth / OpenID。 有一个称为Identity Server 4的开源.net核心实现。

但是,要回答您的问题,您可以创建一个自定义属性来验证传递给您的操作的密钥,也可以在每个操作中简单地进行验证。 .net核心中没有内置方法可以执行此操作,因此您将必须像传递给Web api的任何其他值一样手动处理api密钥。

从听起来看来,您想要实现的是替代的身份验证系统和使用此key查询字符串参数的自定义授权系统(这可能不是最佳设计)。

第一步将是基于此QueryString参数对用户进行身份验证。 现在,最好的方法(IMO)是滚动您自己的身份验证处理程序。 查看Aspnet Security的代码可揭示其某些现有身份验证系统的内部工作原理。

实际上,我们要做的是及早拦截请求,以验证此key的存在,然后对请求进行身份验证。

以下内容显示了此基本系统。

public class QueryStringAuthOptions : AuthenticationOptions
{
    public const string QueryStringAuthSchema = "QueryStringAuth";
    public const string QueryStringAuthClaim = "QueryStringKey";

    public QueryStringAuthOptions()
    {
        AuthenticationScheme = QueryStringAuthSchema;
    }

    public string QueryStringKeyParam { get; set; } = "key";

    public string ClaimsTypeName { get; set; } = "QueryStringKey";

    public AuthenticationProperties AuthenticationProperties { get; set; } = new AuthenticationProperties();
}

public class QueryStringAuthHandler : AuthenticationHandler<QueryStringAuthOptions>
{
    /// <summary>
    /// Handle authenticate async
    /// </summary>
    /// <returns></returns>
    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (Request.Query.TryGetValue(Options.QueryStringKeyParam, out StringValues value) && value.Count > 0)
        {
            var key = value[0];

            //..do your authentication...

            if (!string.IsNullOrWhiteSpace(key))
            {
                //setup you claim
                var claimsPrinciple = new ClaimsPrincipal();
                claimsPrinciple.AddIdentity(new ClaimsIdentity(new[] { new Claim(Options.ClaimsTypeName, key) }, Options.AuthenticationScheme));

                //create the result ticket
                var ticket = new AuthenticationTicket(claimsPrinciple, Options.AuthenticationProperties, Options.AuthenticationScheme);
                var result = AuthenticateResult.Success(ticket);
                return Task.FromResult(result);
            }
        }
        return Task.FromResult(AuthenticateResult.Fail("Key not found or not valid"));

    }
}

现在,上面已经很简单了,我们创建了一个自定义AuthenticationOptions类,将在自定义AuthenticationHandler 如您所见,这非常简单,但是最后我们将创建一个有效的身份验证票证( ClaimsPrinciple )并使用Success结果或Fail()响应。

接下来,我们需要在.Net管道中运行身份验证系统(请注意,这是1.2,因为2.0已更改,请参阅Auth 2.0 Migration )。 这是通过AuthenticationMiddleware完成的,因此在我们创建中间件的简单实现之前。

public class QueryStringAuthMiddleware : AuthenticationMiddleware<QueryStringAuthOptions>
{
    public QueryStringAuthMiddleware(RequestDelegate next, IOptions<QueryStringAuthOptions> options, ILoggerFactory loggerFactory, UrlEncoder encoder)
        : base(next, options, loggerFactory, encoder)
    {
    }

    protected override AuthenticationHandler<QueryStringAuthOptions> CreateHandler()
    {
        return new QueryStringAuthHandler();
    }
}

这确实很基础,但是只是创建一个新的QueryStringAuthHandler()来处理Authenticate请求。 (我们之前创建的那个)。 现在,我们需要将该中间件放入管道中。 因此,遵循.Net约定,静态扩展类可以通过管理选项来实现此目的。

public static class QueryStringAuthMiddlewareExtensions
{
    public static IApplicationBuilder UseQueryStringAuthentication(this IApplicationBuilder appBuilder)
    {
        if (appBuilder == null)
            throw new ArgumentNullException(nameof(appBuilder));

        var options = new QueryStringAuthOptions();
        return appBuilder.UseQueryStringAuthentication(options);
    }

    public static IApplicationBuilder UseQueryStringAuthentication(this IApplicationBuilder appBuilder, Action<QueryStringAuthOptions> optionsAction)
    {
        if (appBuilder == null)
            throw new ArgumentNullException(nameof(appBuilder));

        var options = new QueryStringAuthOptions();
        optionsAction?.Invoke(options);
        return appBuilder.UseQueryStringAuthentication(options);
    }

    public static IApplicationBuilder UseQueryStringAuthentication(this IApplicationBuilder appBuilder, QueryStringAuthOptions options)
    {
        if (appBuilder == null)
            throw new ArgumentNullException(nameof(appBuilder));

        if (options == null)
            throw new ArgumentNullException(nameof(options));

        return appBuilder.UseMiddleware<QueryStringAuthMiddleware>(Options.Create(options));
    }
}

到目前为止,还需要很多代码才能安装Authentication系统,但这是.net核心团队提供的许多示例的后续步骤。

身份验证中间件起作用的最后一步是修改startup.cs文件并添加身份验证系统。

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(); //adds the auth services
    services.AddMvc();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseQueryStringAuthentication(); //add our query string auth

    //add mvc last
    app.UseMvc();
}

我们已经快到了,到目前为止,我们已经有了用于验证请求的机制,最好的是我们创建声明(可以扩展)以在需要时保存更多信息。 最后一步是Authorize请求。 这很容易,我们需要做的就是告诉默认的“授权处理程序”,它在您正在使用的模式中进行登录,此外,我们还将要求我们早先应用的声明。 回到startup.cs中的ConfigureServices方法中,我们只需使用一些设置进行AddAuthorization

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthorization(o =>
    {
        //override the default policy
        o.DefaultPolicy =  new AuthorizationPolicy(new[] { new ClaimsAuthorizationRequirement(QueryStringAuthOptions.QueryStringAuthClaim, new string[0]) }, new[] { QueryStringAuthOptions.QueryStringAuthSchema });

        //or add a policy
        //o.AddPolicy("QueryKeyPolicy", options =>
        //{
        //    options.RequireClaim(QueryStringAuthOptions.QueryStringAuthClaim);
        //    options.AddAuthenticationSchemes(QueryStringAuthOptions.QueryStringAuthSchema);
        //});

    });
    services.AddAuthentication(o =>
    {
        o.SignInScheme = QueryStringAuthOptions.QueryStringAuthSchema;
    }); //adds the auth services
    services.AddMvc();
}

在以上代码段中,我们有两个选择。

  1. 覆盖DefaultPolicy
  2. 将新Policy添加到授权系统。

现在,由您使用哪个选项由您决定。 使用后面的选项要求您明确告知Authorization处理程序要使用哪个AuthorizationPolicy

建议您阅读基于自定义策略的授权以了解这些工作原理。

要使用此授权系统(取决于上面的选项),您可以简单地用AuthorizeAttribute()装饰控制器(如果使用第二个选项,则使用策略名称)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM