ASP0026:[Authorize] 被来自“更远位置”的 [AllowAnonymous] 替代

规则 ID ASP0026
类别 使用情况
修复是中断修复还是非中断修复 非中断

原因

似乎可以直观地认为,与 [AllowAnonymous] 特性相比,距离 MVC 操作“更近”的 [Authorize] 特性会替代 [AllowAnonymous] 特性并强制授权。 但情况并非必然如此。 重要的是特性的相对顺序。

以下代码演示了距离更近的 [Authorize] 特性被距离更远的 [AllowAnonymous] 特性替代的示例。

[AllowAnonymous]
public class MyController
{
    [Authorize] // Overridden by the [AllowAnonymous] attribute on the class
    public IActionResult Private() => null;
}
[AllowAnonymous]
public class MyControllerAnon : ControllerBase
{
}

[Authorize] // Overridden by the [AllowAnonymous] attribute on MyControllerAnon
public class MyControllerInherited : MyControllerAnon
{
}

public class MyControllerInherited2 : MyControllerAnon
{
    [Authorize] // Overridden by the [AllowAnonymous] attribute on MyControllerAnon
    public IActionResult Private() => null;
}
[AllowAnonymous]
[Authorize] // Overridden by the preceding [AllowAnonymous]
public class MyControllerMultiple : ControllerBase
{
}

规则说明

警告 [Authorize] 属性被来自“更远位置”的 [AllowAnonymous] 属性替代。

如何解决冲突

如果看到此警告,要采取的正确操作取决于特性背后的意图。 如果位置更远的 [AllowAnonymous] 特性无意中向匿名用户公开了终结点,则应移除该特性。 如果 [AllowAnonymous] 特性旨在替代位置更近的 [Authorize] 特性,则可以在 [Authorize] 特性后重复 [AllowAnonymous] 特性来阐明意图。

[AllowAnonymous]
public class MyController
{
    // This produces no warning because the second, "closer" [AllowAnonymous]
    // clarifies that [Authorize] is intentionally overridden.
    // Specifying AuthenticationSchemes can still be useful
    // for endpoints that allow but don't require authenticated users.
    [Authorize(AuthenticationSchemes = "Cookies")]
    [AllowAnonymous]
    public IActionResult Privacy() => null;
}

何时禁止显示警告

此诊断的严重性级别为“信息”。 如果你的意图是替代 [Authorize] 属性,则可以禁止显示警告。 但是,建议在 [Authorize] 属性之后重复 [AllowAnonymous] 属性,从而明确意图。