为什么身份验证适用于端点,而不适用于MapWhen



我向WebApplication添加了BasicAuthentication
我使用了此教程:
https://www.roundthecode.com/dotnet/how-to-add-basic-authentication-to-asp-net-core-application

当我在端点上使用它时,效果很好
但当我将它与MapWhen一起使用时,它没有任何效果(几乎在所有地方都添加了UseAuthentication和UseAuthorization,但没有用…(。

为什么这在MapWen中不起作用

我在MapWhen中所做的就是检查请求路径是否以<rootPath>开头,如果是,请使用这个中间件。

这是我的中间件+扩展
同时,我发现了如何添加带有端点的中间件。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;

namespace IdentiyService
{

// https://github.com/dotnet/aspnetcore/blob/146f49fdf09916d0c63e82570bfe059d7fb845e6/src/Middleware/HealthChecks/src/Builder/HealthCheckEndpointRouteBuilderExtensions.cs
public static class JsonServiceMiddlewareExtensions
{

public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseMockJson(
this Microsoft.AspNetCore.Builder.IApplicationBuilder builder
, string rootPath, Microsoft.AspNetCore.Hosting.IWebHostEnvironment env, string jsonFile)
{
// This works fine 
#if USE_ENDPOINTS

IApplicationBuilder x = builder.UseEndpoints(endpoints =>
{
Microsoft.AspNetCore.Http.RequestDelegate pipeline = endpoints.CreateApplicationBuilder()
.UseMiddleware<JsonServiceMiddleware>(env, jsonFile)
.Build();
endpoints
.Map(rootPath, pipeline) 
.WithDisplayName("MockJson")
// .RequireAuthorization("BasicAuthentication")
;
});
#else
// And this just doesn't want to work ...
IApplicationBuilder x = Microsoft.AspNetCore.Builder.MapWhenExtensions.MapWhen(builder,
// ctx => ctx.Request.Path.StartsWithSegments(rootPath, System.StringComparison.InvariantCultureIgnoreCase),
delegate (Microsoft.AspNetCore.Http.HttpContext ctx)
{
bool ret = ctx.Request.Path.StartsWithSegments(rootPath, System.StringComparison.InvariantCultureIgnoreCase);
return ret;
}
,
delegate (Microsoft.AspNetCore.Builder.IApplicationBuilder app)
{
IApplicationBuilder fsck = app.UseRouting().UseAuthentication().UseAuthorization();
// app.UseAuthentication().UseAuthorization();

IApplicationBuilder foo = Microsoft.AspNetCore.Builder.UseMiddlewareExtensions
.UseMiddleware<JsonServiceMiddleware>(
fsck // app
, env
, jsonFile
);

foo.UseAuthentication().UseAuthorization();
// Microsoft.AspNetCore.Builder.AuthAppBuilderExtensions.UseAuthentication(app);
}
);
x = x.UseAuthentication().UseAuthorization();
#endif
return x;
} // End Extension method UseMockJson 

} // End Class JsonServiceMiddlewareExtensions 

// [Middleware.BasicAuthorization()] // has no effect ...
public class JsonServiceMiddleware
{
private readonly Microsoft.AspNetCore.Http.RequestDelegate next;
private readonly Microsoft.AspNetCore.Hosting.IWebHostEnvironment m_env;
private readonly string m_jsonFile;

public JsonServiceMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next,
Microsoft.AspNetCore.Hosting.IWebHostEnvironment env,
string jsonFile)
{
this.next = next;
this.m_env = env;
this.m_jsonFile = jsonFile;
} // End Constructor 

// https://localhost:44373/api/jid/v1/units
[Middleware.BasicAuthorization()] // this has EFFECT !
public async System.Threading.Tasks.Task InvokeAsync(Microsoft.AspNetCore.Http.HttpContext context)
{
RouteData route = context.GetRouteData();
string name = (string)route.Values["name"];
// string path = System.IO.Path.Combine(m_env.ContentRootPath, "json");
// string result = FindFile(path, name+".json");
// System.Console.WriteLine(result);
if (name == null)
{
// context.Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
// return;
name = System.IO.Path.GetFileNameWithoutExtension(this.m_jsonFile);
}
name = name.ToLowerInvariant();

string output = @"{ 
""type"": """ + m_jsonFile + @""",
""webRoot"": """ + m_env.WebRootPath + @""",
""contentRoot"": """ + m_env.ContentRootPath + @"""
}";
// output = System.IO.Path.Combine(m_env.ContentRootPath, "json", this.m_jsonFile);
output = System.IO.Path.Combine(m_env.ContentRootPath, "json", name + ".json");
output = System.IO.Path.GetFullPath(output);
if (!output.StartsWith(m_env.ContentRootPath))
{
// context.Response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
context.Response.StatusCode = (int)System.Net.HttpStatusCode.UnavailableForLegalReasons;
return;
}
if (!System.IO.File.Exists(output))
{
context.Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
return;
}

output = System.IO.File.ReadAllText(output, System.Text.Encoding.UTF8);

// userType = EmployeeUser
// modifiedSince = 2021 - 06 - 23T04 % 3A40 % 3A36Z

context.Response.StatusCode = 200;
context.Response.ContentType = "application/json; charset=utf-8";
await Microsoft.AspNetCore.Http.HttpResponseWritingExtensions.WriteAsync(context.Response, output);
} // End Task InvokeAsync 

} // End Class JsonServiceMiddleware 

}

这是我的Startup.cs

using IdentiyService.Middleware;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IdentiyService
{

public class Startup
{
public IConfiguration Configuration { get; }

public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication().AddScheme<
Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions,
Middleware.BasicAuthenticationHandler>("BasicAuthentication", options => { });

services.AddAuthorization(options =>
{
options.AddPolicy("BasicAuthentication", 
new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder("BasicAuthentication")
.RequireAuthenticatedUser()
.Build()
);
});

// services.AddHealthChecks();

// https://dotnetcoretutorials.com/2017/01/24/using-gzip-compression-asp-net-core/
// services.AddResponseCompression();
services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add(new BrotliCompressionProvider());
options.Providers.Add(new GzipCompressionProvider());
options.Providers.Add(new DeflateCompressionProvider());
// https://github.com/MikeStall/DataTable
// https://github.com/stevehansen/csv/
// https://joshclose.github.io/CsvHelper/
// https://joshclose.github.io/CsvHelper/examples/
// https://github.com/JoshClose/CsvHelper
options.MimeTypes = new[] {
"text/plain", "text/html", "text/css", "text/csv"
,"application/javascript", "application/json", "application/xml"
,"image/x-icon", "image/png", "image/gif", "image/jpeg", "image/webp", "image/tiff", "image/svg+xml"
};
});
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "IdentiyService", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "IdentiyService v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

// app.UseWhen(x => true, delegate(IApplicationBuilder app) { });

// Why is this not working ? No matter what I do, it has absolutely no effect ... 
// But it works just fine with endpoints ? 

// https://localhost:44373/api/jid/v1/buildings
app.UseMockJson("/api/jid/v1/buildings", env, "buildings.json").UseAuthentication().UseAuthorization();
// https://localhost:44373/api/jid/v1/units
app.UseMockJson("/api/jid/v1/units", env, "units.json").UseAuthentication().UseAuthorization();
// https://localhost:44373/api/jid/v1/users
app.UseMockJson("/api/jid/v1/users", env, "users.json").UseAuthentication().UseAuthorization();

// This is for use with EndPoints
// app.UseMockJson("/api/jid/v1/{name}", env, "users.json");

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
// https://learn.microsoft.com/en-us/answers/questions/528683/how-to-do-authorization-for-usehealthcheck-middlew.html
// IEndpointConventionBuilder ep = endpoints.MapHealthChecks("/health");
// ep.RequireAuthorization();
endpoints.MapSomeMiddleware("/foo").RequireAuthorization("BasicAuthentication");
}); //.UseAuthentication().UseAuthorization();

}

}

}

回答我自己的问题。

显然,UseAuthentication((和UseAuthorization((被认为只用于端点

因此,如果您使用UseAuthentication/UseAuthorization应用UseMiddleware,则身份验证/授权不适用于此中间件。

唯一的问题是名字。它是为端点设计的,所以你不能用它来保护文件夹或其他东西。

这也解释了为什么必须在UseRouting之后和UseEndpoints之前应用UseAuthentication/UseAuthorization。

它必须在逻辑上跟在UseRouting之后,以便路由信息可用用于身份验证决策
但在UseEndpoints之前,以便在访问端点之前对用户进行身份验证。

这很有道理。在您还不知道请求了哪个端点以及该端点是否需要身份验证(授权与否(之前,就试图弄清楚请求是否得到了授权,这将是愚蠢的

Als应用程序。UseAddAuthentication((是一个交叉问题,它发生在应用路由之后
因此,并非所有路由都会应用身份验证。

因此,当您使用UseAuthentication/UseAuthorization/UseAddAuthentication时要小心——它可能实际上并没有达到名称所暗示的效果——这是相当危险的。

相关内容

  • 没有找到相关文章

最新更新