授权属性无法阻止 ASP.Net Core 3.0 Web API 中的请求

Hoo*_*lum 2 c# authentication authorization asp.net-core-webapi

我正在尝试在 ASP.Net Core 3.0 Web Api 项目中使用基于 cookie 的身份验证。

目前,我的配置服务如下所示:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());
        });

        services.AddAuthentication(options => 
            {
                options.DefaultScheme = "Cookies";
            })
            .AddCookie("Cookies", options => 
            {
                options.Cookie.Name = "auth_cookie";
                options.Cookie.SameSite = SameSiteMode.None;
                options.Events = new CookieAuthenticationEvents
                {
                    OnRedirectToLogin = redirectContext =>
                    {
                        redirectContext.HttpContext.Response.StatusCode = 401;
                        return Task.CompletedTask;
                    }
                };
            });

        services.AddAuthorization();

        services.AddControllers();
    }
Run Code Online (Sandbox Code Playgroud)

我的配置方法如下所示:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCors("CorsPolicy");

        app.UseHttpsRedirection();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers().RequireAuthorization();
        });
    }
Run Code Online (Sandbox Code Playgroud)

我将 [Microsoft.AspNetCore.Authorization.Authorize] 属性应用到默认生成的 WeatherForecastController,并浏览到相关页面。我预计会收到失败,因为我的请求中没有 cookie,但是页面加载没有问题。

检查调试日志,我可以看到以下内容:

Microsoft.Extensions.Hosting.Internal.Host: Debug: Hosting started
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 GET https://localhost:44376/weatherforecast  
Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware: Debug: Wildcard detected, all requests with hosts will be allowed.
***Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler: Debug: AuthenticationScheme: Cookies was not authenticated.***
Microsoft.AspNetCore.Routing.Matching.DfaMatcher: Debug: 1 candidate(s) found for the request path '/weatherforecast'
Microsoft.AspNetCore.Routing.Matching.DfaMatcher: Debug: Endpoint 'NotesApp.WebApi.Controllers.WeatherForecastController.Get (NotesApp.WebApi)' with route pattern 'WeatherForecast' is valid for the request path '/weatherforecast'
Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware: Debug: Request matched endpoint 'NotesApp.WebApi.Controllers.WeatherForecastController.Get (NotesApp.WebApi)'
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'NotesApp.WebApi.Controllers.WeatherForecastController.Get (NotesApp.WebApi)'
Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory: Debug: Registered model binder providers, in the following order: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BinderTypeModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ServicesModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatingPointTypeModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.EnumTypeModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CancellationTokenModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinderProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinderProvider
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "Get", controller = "WeatherForecast"}. Executing controller action with signature System.Collections.Generic.IEnumerable`1[NotesApp.WebApi.WeatherForecast] Get() on controller NotesApp.WebApi.Controllers.WeatherForecastController (NotesApp.WebApi).
***Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Execution plan of authorization filters (in the following order): None***
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Execution plan of resource filters (in the following order): None
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Execution plan of action filters (in the following order): Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter (Order: -3000), Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter (Order: -2000)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Execution plan of exception filters (in the following order): None
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Execution plan of result filters (in the following order): Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter (Order: -2000)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Executing controller factory for controller NotesApp.WebApi.Controllers.WeatherForecastController (NotesApp.WebApi)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Debug: Executed controller factory for controller NotesApp.WebApi.Controllers.WeatherForecastController (NotesApp.WebApi)
Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector: Debug: List of registered output formatters, in the following order: Microsoft.AspNetCore.Mvc.Formatters.HttpNoContentOutputFormatter, Microsoft.AspNetCore.Mvc.Formatters.StringOutputFormatter, Microsoft.AspNetCore.Mvc.Formatters.StreamOutputFormatter, Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter
Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector: Debug: No information found on request to perform content negotiation.
Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector: Debug: Attempting to select an output formatter without using a content type as no explicit content types were specified for the response.
Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector: Debug: Attempting to select the first formatter in the output formatters list which can write the result.
Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector: Debug: Selected output formatter 'Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter' and content type 'application/json' to write the response.
Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor: Information: Executing ObjectResult, writing value of type 'NotesApp.WebApi.WeatherForecast[]'.
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action NotesApp.WebApi.Controllers.WeatherForecastController.Get (NotesApp.WebApi) in 65.9499ms
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'NotesApp.WebApi.Controllers.WeatherForecastController.Get (NotesApp.WebApi)'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 182.95000000000002ms 200 application/json; charset=utf-8
Run Code Online (Sandbox Code Playgroud)

请注意我加星号的两行 - 第一行正确的代码表明我们没有通过 cookie 方案的身份验证。然而,第二个表明控制器上没有授权过滤器,这令人费解,因为确实有。这大概就是允许该请求的原因。

[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

谁能解释一下为什么运行时未检测到授权属性并对其执行操作?

我现在不太关心 cookie 的机制,我只想正确阻止控制器。

非常感谢

小智 6

通过禁用端点路由,您实际上会退回到 2.x 路由。为了解决这个问题,您应该确保使用正确的顺序构建管道:

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers().RequireAuthorization();
});
Run Code Online (Sandbox Code Playgroud)