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

2024-01-20

网站默认只能匿名访问。

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

为了实现这一点,我首先配置了 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();
}

然后在相关控制器上,我放了一个[Authorize]属性。

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

这工作得很好——当授权属性存在时,cookie 验证就会启动。到目前为止,一切都很好。

现在我想要disable授权在运行时当维护模式关闭时。

尝试的解决方案

这是我经过大量尝试、错误和研究后得到的结果。

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 身份验证仍然会启动并需要身份验证。我可以删除它并尝试实现我自己的身份验证,但当我们已经内置了精心设计的解决方案时,这将是愚蠢的。

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

Notes:

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

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


是的你可以!

ASP.NET Core 中的授权系统是可扩展的,您可以使用以下命令轻松实现您的场景基于策略的授权 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2.

开始之前需要了解两件主要事情:

  • 授权策略由一个或多个组成要求 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2#requirements-1
  • 政策要想成功就必须满足所有要求

我们的目标是创建一个要求,如果以下任何陈述为真,则满足该要求:

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

我们来看看代码吧!

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

public class MaintenanceModeDisabledOrAuthenticatedUserRequirement : IAuthorizationRequirement
{
}

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

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;
    }
}

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

  • 您可以重新定义默认策略,当“空”时使用[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,如所示官方文档 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2#handler-registration-1

// 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]根据需要在控制器/操作上添加属性。

// 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();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Asp.Net Core 2.2 中禁用/启用运行时身份验证? 的相关文章

  • 起订量要求?违背了目的?

    是否需要虚拟化您想要模拟的所有属性访问器就违背了模拟的目的 我的意思是 如果我必须修改我的对象并虚拟化我想要模拟的每个访问器 我难道不能继承我的类并自己模拟它吗 你的问题非常有效 但如果你仔细想想 没有其他方法可以模拟课程 如果你采用一个接
  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 如何从RichTextBox中获取显示的文本?

    如何获得显示的RichTextBox 中的文本 我的意思是 如果 RichTextBox 滚动到末尾 我只想接收那些对我来说可见的行 P S 获得第一个显示的字符串就足够了 您想使用 RichTextBox GetCharIndexFrom
  • 如何使用 MVVM 更新 WPF 中编辑的数据? [复制]

    这个问题在这里已经有答案了 我正在为聊天应用程序构建 UI 设计 在尝试更新所选联系人的消息时遇到问题 选择现有联系人 选择编辑选项 然后编辑其属性 例如用户名和图像 后 唯一进行的更改是联系人的用户名和图像 我仍然想更改 MessageM
  • 如何在 Asp.net Gridview 列中添加复选框单击事件

    我在 asp 中有一个 gridview 其中我添加了第一列作为复选框列 现在我想选择此列并获取该行的 id 值 但我不知道该怎么做 这是我的 Aspx 代码
  • 序列化和反序列化 Visual Studio 解决方案文件 - 或以编程方式编辑?

    我想以编程方式添加和删除项目 解决方案文件夹和其他项目 例如解决方案的资源文件 但我不确定最好的方法是什么 对于那些不知道的人 高度简化 解决方案文件 sln 通常如下所示 Microsoft Visual Studio Solution
  • 单线程公寓问题

    从我的主窗体中 我调用以下命令来打开一个新窗体 MyForm sth new MyForm sth show 一切都很好 但是这个表单有一个组合框 当我将其 AutoCompleteMode 切换为建议和追加时 我在显示表单时遇到了这个异常
  • 我可以仅在少数情况下关闭模拟吗

    我有一个始终使用模拟的应用程序 但是 当用户以管理员身份登录时 一些操作需要他们写入服务器本身 现在 如果这些用户在实际服务器上没有权限 有些用户没有 则不会让他们写入 我想做的是关闭几个命令的模拟 有没有办法做这样的事情 using Ho
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • dropdownlist DataTextField 由属性组成?

    有没有一种方法可以通过 C 使 asp net 中的下拉列表的 datatextfield 属性由对象的多个属性组成 public class MyObject public int Id get set public string Nam
  • 在VisualStudio DTE中,如何获取ActiveDocument的内容?

    我正在 VisualStudio 中编写脚本 并尝试获取当前 ActiveDocument 的内容 这是我当前的解决方案 var visualStudio new API VisualStudio 2010 var vsDTE visual
  • 系统错误 124 - SHFileOperation 的 ERROR_INVALID_LEVEL

    我在使用时遇到问题SHFileOperation SHFileOperation SHFILEOPSTRUCT https stackoverflow com questions 9191415 shfileoperation shfile
  • 从事务范围调用 WCF 服务方法

    我有这样的代码 using TransactionScope scope TransactionScopeFactory CreateTransactionScope some methodes calls for which scope
  • 使用(linq to sql)更新错误

    我有两个表 通过外键 CarrierID 绑定 Carrier CarrierID CarrierName CarrierID 1 CarrierName DHL CarrierID 2 CarrierName Fedex Vendor V
  • 从 C 线程调用 Python 代码

    我对从 C 或 C 线程调用 Python 代码时如何确保线程安全感到非常困惑 The Python 文档 http docs python org c api init html non python created threads似乎是
  • 如何将对象转换为传递给函数的类型?

    这不会编译 但我想做的只是将对象转换为传递给函数的 t public void My Func Object input Type t t object ab TypeDescriptor GetConverter t ConvertFro
  • 如何获取 QIcon 的文件/资源​​路径

    假设我做了这样的事情 QIcon myIcon resources icon ico 我稍后如何确定该图标的路径 例如 QString path myIcon getPath 问题是 没有getPath 会员 我找不到类似的东西 但肯定有办
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • c# 模拟 IFormFile CopyToAsync() 方法

    我正在对一个异步函数进行单元测试 该函数将 IFormFile 列表转换为我自己的任意数据库文件类列表 将文件数据转换为字节数组的方法是 internal async Task
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个

随机推荐

  • 使用共享代码分离前端和后端的 package.json

    我有一个项目 有一个单独的前端 webpack 和后端 express mongodb 我想分开 the package json同时即将在它们之间共享一些逻辑 实用代码 我如何组织我的文件结构 以便我可以适当地分离它们的依赖关系 现在这是
  • 从 edmx 模型生成 odata 类

    我正在尝试在另一个 ODATA API 的代码中使用来自现有 ODATA 端点的数据 我不想手动重新创建所有模型 因此我希望使用现有的 edmx 模型在 C 中创建我需要的类 我研究了 Microsoft 提供的 odata 客户端代码生成
  • 为此获得提升::shared_ptr

    我正在广泛使用boost shared ptr在我的代码中 事实上 大多数分配在堆上的对象都由一个shared ptr 不幸的是 这意味着我无法通过this进入任何需要一个函数shared ptr 考虑这段代码 void bar boost
  • Checkstyle - 仅检查接口中的方法

    是否可以仅对接口中的方法应用 JavadocMethod 检查器 不在实现类中 我们也有计划实施 敬请关注issue https github com sevntu checkstyle sevntu checkstyle issues 7
  • CDK将API网关堆栈分成2个小堆栈

    我正在尝试创建一个 CDK 堆栈来创建 API 网关 如果我以 小块 形式创建堆栈 资源的注释部分 则一切都会正常工作 但是当我尝试创建完整的堆栈时 我收到此异常 Number of resources 224 is greater tha
  • 为 Mac 编译 stasm

    我正在尝试在我的 mac 上构建 stasm 库 并希望将其移植到 iphone 上 斯塔姆下载 http www milbo users sonic net stasm download html http www milbo users
  • 使用 Eclipse Juno Java EE 进行 jQuery 自动补全

    我已经阅读了一些关于如何为 Eclipse 启用 jQuery 特别是自动完成 支持的日期信息 使用 Aptana 或其他插件 我尝试过 Aptana 3 版本插件 但除了问题之外什么也没得到 有人可以解释如何实现这一目标吗 也许现在 Ap
  • PageControl 禁用选项卡上的文本 - 灰色文本

    我正在寻找 我认为 可以在 TPageControl 组件的 OnDrawTab 事件中使用的 Windows API 以在我选择的选项卡上显示灰色文本 我过去曾经这样做过 根据记忆 这就是我所做的 在 OnDrawTab 事件中 不幸的是
  • 有没有办法对 Firebase 用户创建和/或密码重置进行电子邮件确认?

    问题说明了一切 在 Firebase 中 当用户创建帐户时如何确认电子邮件 或者通过电子邮件重置密码 我可以更广泛地问 有什么方法可以从 Firebase 发送电子邮件吗 例如 通知等 这不是您通常在客户端执行的操作 Update 请注意
  • 在 Visual Studio 2010 中更改文本光标/插入符号

    我不小心将 Visual Studio 2010 中的文本光标 插入符号从一行更改为带有突出显示整个字符的框的光标 但不知道如何将其更改回来 谁能告诉我怎么做 谢谢 按插入键
  • 如何将可观察集合写入txt文件?

    将可观察集合写入 txt 文件的最佳方法是什么 我目前有以下内容 public ObservableCollection
  • pytqt图形线的鼠标坐标

    每当我将鼠标移动到图表顶部时 我都试图获取随机函数图的 x y 值 我正在使用 pyqtgraph SignalProxy 并将其连接到回调 mousedMoved 我收到此错误 NameError 未定义全局名称 mouseMoved 这
  • 在 Play 2.x 中覆盖 WebJar 资源

    只是想知道 是否有一种方法可以在一个文件中覆盖某些资产 确切地说是 JS 和 LESS 文件WebJars http www webjars org 资产与位于app assets 目录 说吧 我有一个引导程序 3 1 1 webjar h
  • 将 Matplotlib 图形保存为全屏图像

    我正在使用 Pandas 和 MatPlotLib 构建一个小型图形实用程序来解析工作机器中的数据和输出图形 当我使用输出图表时 plt show 我最终得到了一个不清晰的图像 其中的图例和标签就像这样相互排斥 However expand
  • 无法使用 pip 安装 Python 成像库

    尝试使用 PIP 安装 Python Imaging Library PIL 时 安装失败并出现以下错误 SyntaxError invalid syntax Complete output from command python setu
  • 没有找到类“androidx.core.widget.DrawerLayout”

    使用 Android Studio 菜单选项 Refactor gt Refactor to Androidx 迁移到 Androidx 包后 我的 build gradle 看起来像 implementation androidx app
  • facebook graph api 和 php sdk,删除事件!

    在我的一生中 我找不到一种方法来删除 取消或移除我使用 FB PHP SDK 和 Graph API 创建和更新的 Facebook 事件 我已经尝试了 facebook 文档和堆栈溢出中找到的每一个排列 以下是我在探索中发现的一些线索 h
  • 适合初学者的松耦合和面向对象实践

    保持类松散耦合是编写易于理解 修改和调试的代码的一个重要方面 我明白了 然而 作为一个新手 几乎任何时候我都很难超越最简单的例子 我或多或少地了解如何将字符串 整数和简单数据类型封装在它们自己的类中 然而 当我开始处理富文本格式等信息时 事
  • 在Linux上安装特定的adb版本

    我想使用特定的 adb 版本来连接设备 为了连接外部模拟器 我尝试使用adb connect localhost 5555 我得到这个结果 adb adb server version 36 doesn t match this clien
  • 如何在 Asp.Net Core 2.2 中禁用/启用运行时身份验证?

    网站默认只能匿名访问 管理员有一个按钮可以将站点切换到维护模式 这应该使用内置的 Cookie 身份验证启用授权 在数据库中稍微翻转一下 与本文无关 为了实现这一点 我首先配置了 cookie 身份验证 在startup cs中 publi