gpt4 book ai didi

c# - 如何在 Asp.Net Core 2.2 中在运行时禁用/启用身份验证?

转载 作者:行者123 更新时间:2023-12-05 01:13:20 24 4
gpt4 key购买 nike

默认情况下,网站只能匿名访问。

管理员有一个按钮可以将站点切换到维护模式,这应该使用内置的 CookieAuthentication 启用授权(在数据库中翻转一点,与本文无关)。

为了使这项工作,我首先配置了 cookie 身份验证(在 startup.cs 中):

public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = new PathString("/auth/login");
});
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
}

然后在相关的 Controller 上,我放了一个[Authorize]属性。

[Authorize]
public class HomeController : Controller
{
//removed
}

这非常有效——当授权属性存在时,cookie auth 就会启动。到目前为止一切顺利。

现在我想在维护模式关闭时禁用授权在运行时

尝试的解决方案

这是我经过大量反复试验和研究后得出的结论。

public void OnAuthorization(AuthorizationFilterContext context)
{
IMaintenanceModeDataService ds = context.HttpContext.RequestServices.GetService<IMaintenanceModeDataService>();

if (!ds.IsMaintenanceModeEnabled)
{
//Maintenance mode is off, no need for authorization
return;
}
else
{
ClaimsPrincipal user = context.HttpContext.User;
if (user.Identity.IsAuthenticated)
{
//when the user is authenticated, we don't need to do anything else.
return;
}
else
{
//we're in maintenance mode AND the user is not
//It is outside the scope of this to redirect to a login
//We just want to display maintenancemode.html
context.Result = new RedirectResult("/maintenancemode.html");
return;
}
}
}

[MaintenanceModeAwareAuthorize]
public class HomeController : Controller
{
//removed
}

这在站点处于维护模式时非常有用。

当站点未处于维护模式时,cookie 身份验证仍会启动并需要身份验证。我可以删除它并尝试实现我自己的身份验证,但是当我们已经内置了精心设计的解决方案时,那将是愚蠢的。

当站点未处于维护模式(运行时)时,如何禁用授权?

注意事项:

问:为什么不通过 x 来处理这个问题(这需要服务器端访问配置、环境变量、服务器或类似内容)?

答:因为非技术管理员用户需要通过单击后端的按钮立即访问它。

最佳答案

是的,你可以!

ASP.NET Core 中的授权系统是可扩展的,您可以使用 poliy-based authorization 轻松实现您的场景.

开始前要知道的两个主要事项:

  • 授权策略由一个或多个 requirements 组成
  • 必须满足所有要求才能使政策成功

我们的目标是创建一个满足以下任一陈述的需求:

  • 未启用维护模式,或
  • 用户已通过身份验证

让我们看看代码!

第一步是创建我们的需求:

public class MaintenanceModeDisabledOrAuthenticatedUserRequirement : IAuthorizationRequirement
{
}

然后我们必须实现这个要求的处理程序,它将确定它是否满足。好消息是处理程序支持依赖注入(inject):

public class MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler : AuthorizationHandler<MaintenanceModeDisabledOrAuthenticatedUserRequirement>
{
private readonly IMaintenanceModeDataService _maintenanceModeService;

public MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler(IMaintenanceModeDataService maintenanceModeService)
{
_maintenanceModeService = maintenanceModeService;
}

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MaintenanceModeDisabledOrAuthenticatedUserRequirement requirement)
{
if (!_maintenanceModeService.IsMaintenanceModeEnabled || context.User.Identities.Any(x => x.IsAuthenticated))
{
context.Succeed(requirement);
}

return Task.CompletedTask;
}
}

接下来,我们需要创建一个使用此要求的授权策略,您在这里有两个选择:

  • 您可以重新定义默认策略,在“空”时使用 [Authorize]使用属性,或
  • 创建一个必须在属性中引用的显式策略,例如 [Authorize(Policy = "<your-policy-name>")]

没有正确或错误的答案;我会选择第一个选项是我的应用程序只有一个授权策略,如果它有多个授权策略,则选择第二个。我们将看到如何做到这两点:

services
.AddAuthorization(options =>
{
// 1. This is how you redefine the default policy
// By default, it requires the user to be authenticated
//
// See https://github.com/dotnet/aspnetcore/blob/30eec7d2ae99ad86cfd9fca8759bac0214de7b12/src/Security/Authorization/Core/src/AuthorizationOptions.cs#L22-L28
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddRequirements(new MaintenanceModeDisabledOrAuthenticatedUserRequirement())
.Build();

// 2. Define a specific, named policy that you can reference from your [Authorize] attributes
options.AddPolicy("MaintenanceModeDisabledOrAuthenticatedUser", builder => builder
.AddRequirements(new MaintenanceModeDisabledOrAuthenticatedUserRequirement()));
});

接下来,您需要将需求处理程序注册为 IAuthorizationHandler ,如 the official docs 中所示

// The lifetime you pick is up to you
// You just need to remember that it's got a dependency on IMaintenanceModeDataService, so if you
// registered the implementation of IMaintenanceModeDataService as a scoped service, you shouldn't
// register the handler as a singleton
// See this captive dependency article from Mark Seeman: https://blog.ploeh.dk/2014/06/02/captive-dependency/
services.AddScoped<IAuthorizationHandler, MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler>();

最后一步是应用 [Authorize]根据需要在 Controller /操作上添加属性。

// 1. If you redefined the default policy
[Authorize]
public IActionResult Index()
{
return View();
}

// 2. If you defined an explicit policy
[Authorize(Policy = "MaintenanceModeDisabledOrAuthenticatedUser")]
public IActionResult Index()
{
return View();
}

关于c# - 如何在 Asp.Net Core 2.2 中在运行时禁用/启用身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60549828/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com