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

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

原因

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

注释

[AllowAnonymous] 属性不会完全禁用身份验证。 将凭据发送到终结点 [AllowAnonymous]时,终结点仍会对这些凭据进行身份验证并建立用户的标识。 该 [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] 特性无意中向匿名用户公开了终结点,则应移除该特性。 如果 [AllowAnonymous] 特性旨在替代位置更近的 [Authorize] 特性,则可以在 [AllowAnonymous] 特性后重复 [Authorize] 特性来阐明意图。

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

何时禁止显示警告

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