简体   繁体   English

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

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

I have created an API for a back-end in C# ASP Net Core. 我已经在C#ASP Net Core中为后端创建了API。 I am trying to figure our a way to authorize the Routes so that It will take in a API Key in the url such as " https://mywebsite.com/api/data/first?key=VX4HCOjtMQ6ZF978a245oLw00SfK0ahm " to authenticate the Route and present the data in JSON. 我正在尝试找到一种授权路线的方法,以便它将在URL中使用API​​密钥,例如“ https://mywebsite.com/api/data/first?key=VX4HCOjtMQ6ZF978a245oLw00SfK0ahm ”以对路线进行身份验证,并用JSON呈现数据。

I know in ASP NET Core identity there is a way to authenticate the route but that requires the user to login first. 我知道在ASP NET Core身份中,有一种方法可以对路由进行身份验证,但这需要用户先登录。 How can I secure my API Routes with an API Key? 如何使用API​​密钥保护我的API路由?

What you are trying to do will not secure the web api. 您尝试执行的操作不会保护网络api。 I would recommend that you look into OAuth/OpenID. 我建议您研究OAuth / OpenID。 There is an open source .net core implementation called Identity Server 4. 有一个称为Identity Server 4的开源.net核心实现。

However to answer your question you could create a custom attribute to validate the key being passed to your actions, or you could simply handle the validation in each action. 但是,要回答您的问题,您可以创建一个自定义属性来验证传递给您的操作的密钥,也可以在每个操作中简单地进行验证。 There is no built in way to do this in .net core, you will have to manually handle the api key like any other value being passed to your web api. .net核心中没有内置方法可以执行此操作,因此您将必须像传递给Web api的任何其他值一样手动处理api密钥。

From the sounds of it what you are trying to achieve is an alternative Authentication system and a custom Authorization system that uses this key query string parameter (which is probably not the best design). 从听起来看来,您想要实现的是替代的身份验证系统和使用此key查询字符串参数的自定义授权系统(这可能不是最佳设计)。

The first step would be to authenticate the user based on this QueryString parameter. 第一步将是基于此QueryString参数对用户进行身份验证。 Now the best way (IMO) is to roll your own authentication handler. 现在,最好的方法(IMO)是滚动您自己的身份验证处理程序。 Reviewing the code For Aspnet Security reveals the inner workings of some of their existing authentication systems. 查看Aspnet Security的代码可揭示其某些现有身份验证系统的内部工作原理。

Effectively what we will do is intercept the request early on validate the existence of this key and then authenticate the request. 实际上,我们要做的是及早拦截请求,以验证此key的存在,然后对请求进行身份验证。

Something below shows this basic system. 以下内容显示了此基本系统。

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"));

    }
}

Now the above is pretty straight forward we have created a custom AuthenticationOptions class that we will use in our custom AuthenticationHandler . 现在,上面已经很简单了,我们创建了一个自定义AuthenticationOptions类,将在自定义AuthenticationHandler As you see this is very straight forward but in the end we are creating a valid Authentication Ticket ( ClaimsPrinciple ) and responding with a Success result or Fail() . 如您所见,这非常简单,但是最后我们将创建一个有效的身份验证票证( ClaimsPrinciple )并使用Success结果或Fail()响应。

Next we need to get the Authentication system working within the .Net pipeline (note this is 1.2 as 2.0 has changed see Auth 2.0 Migration ). 接下来,我们需要在.Net管道中运行身份验证系统(请注意,这是1.2,因为2.0已更改,请参阅Auth 2.0 Migration )。 This is done through AuthenticationMiddleware so as before we create our simple implementation of the middleware. 这是通过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();
    }
}

This is really basic but just creates a new QueryStringAuthHandler() to handle the Authenticate request. 这确实很基础,但是只是创建一个新的QueryStringAuthHandler()来处理Authenticate请求。 (The one we created earlier). (我们之前创建的那个)。 Now we need to get this middleware into the pipeline. 现在,我们需要将该中间件放入管道中。 So following the .Net convention a static extensions class can do this with the ability to manage the options. 因此,遵循.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));
    }
}

Right so far thats alot of code to get the Authentication system in place, however this is following many of the examples provided by the .net core team. 到目前为止,还需要很多代码才能安装Authentication系统,但这是.net核心团队提供的许多示例的后续步骤。

Final step for the Authentication middleware to work is to modify the startup.cs file and add the authentication systems. 身份验证中间件起作用的最后一步是修改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();
}

We are almost there, to this point we have our mechanisms for authenticating the request, and best we are creating claims (which can be extended) to hold more information if required. 我们已经快到了,到目前为止,我们已经有了用于验证请求的机制,最好的是我们创建声明(可以扩展)以在需要时保存更多信息。 The final step is to Authorize the request. 最后一步是Authorize请求。 This is the easy bit, all we need to do is tell the default Authorization Handlers which sign in schema you are using, and in addition we will also require the claim we applied earlier on. 这很容易,我们需要做的就是告诉默认的“授权处理程序”,它在您正在使用的模式中进行登录,此外,我们还将要求我们早先应用的声明。 Back in the ConfigureServices method in your startup.cs we simply AddAuthorization with some settings. 回到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();
}

In the above snippet we have two options. 在以上代码段中,我们有两个选择。

  1. Override the DefaultPolicy or 覆盖DefaultPolicy
  2. Add a new Policy to the authorization system. 将新Policy添加到授权系统。

Now which option you use is up to you. 现在,由您使用哪个选项由您决定。 Using the later option requires you to explicitly tell the Authorization handler which AuthorizationPolicy to use. 使用后面的选项要求您明确告知Authorization处理程序要使用哪个AuthorizationPolicy

I suggest you read Custom Policy-Based Authorization to understand how these work. 建议您阅读基于自定义策略的授权以了解这些工作原理。

To use this Authorization system (depending on your options above) you can simply decorate your controllers with the AuthorizeAttribute() (with policy name if you used the second option). 要使用此授权系统(取决于上面的选项),您可以简单地用AuthorizeAttribute()装饰控制器(如果使用第二个选项,则使用策略名称)。

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

相关问题 在 ASP.NET CORE Web API 中授权 - Authorize in ASP.NET CORE Web API 你可以[授权]一个不在带有asp.net核心的控制器中的功能吗? - Can you [Authorize] a function that is not in a controller with asp.net core? 如何授权Asp.Net Web API - How to Authorize Asp.Net Web api 如何将图像文件发布到 asp.net core 5 中的 api 控制器? (415 错误) - how do you post an image file to an api controller in asp.net core 5? (415 error) 如何设置 ASP.Net 3.0 Core Web API 项目以使用 AutoFac 和 NLog? - How do you setup an ASP.Net 3.0 Core Web API project to use AutoFac and NLog? 如何让 [Authorize] 属性在 .NET Core 6 Web API 中起作用? - How to get [Authorize] attribute work in .NET Core 6 Web API? 如何在 .net 核心 web api 3.1 中创建 Customtom 授权属性? - How to create Customtom Authorize Attribute in .net core web api 3.1? ASP.NET Web API:如何授权静态HTML内容 - ASP.NET Web API : How to authorize for static HTML content 如何使用curl授权C#Web API调用? - How do you authorize a C# web api call with curl? 用谷歌授权 asp.net 核心 web api(实体框架核心) Z7C82E852FB415F250Z92 - authorize asp.net core web api (entity framework core) with google oauth
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM