ASP .NET Core Razor 页面中的授权
Posted
技术标签:
【中文标题】ASP .NET Core Razor 页面中的授权【英文标题】:Authorization in ASP .NET Core Razor pages 【发布时间】:2019-12-20 00:03:59 【问题描述】:我无法在 ASP .NET Core 中为剃须刀页面上的操作实施基于策略的授权。
我通读了this comprehensive document on authorization 并将其示例作为指导。
Razor 页面操作代码:
[Authorize(Policy = "test")]
public async Task<IActionResult> OnGetCreateAsync(string id)
服务配置中的代码:
_ = services.AddAuthorization(options =>
options.AddPolicy("test", policy =>
policy.RequireAssertion(context =>
false));
);
我希望如果我调用动作或端点服务,例如
GET /Account?handler=Create
然后请求将被拒绝并返回 403 状态响应,因为“测试”政策规定每个人都是未经授权的。但是在实际操作中,动作是成功调用的。
【问题讨论】:
你能在 Startup 中显示你的 Configure 方法吗? 您还需要使用UseAuthentication()
中间件才能使这些授权策略真正发挥作用。
你添加UseAuthentication()中间件了吗
是的。我添加了身份验证中间件。
更新了github.com/dotnet/AspNetCore.Docs/pull/18949/files的文档
【参考方案1】:
Razor Pages 不支持 处理程序 级别的 [Authorize]
。即您只能在PageModel
本身上授权一个页面作为一个整体,如docs 中所述:
策略不能在 Razor 页面处理程序级别应用,它们必须应用于页面。
如果授权整个页面不是一个可行的解决方案,您可能需要将您的 OnGetCreateAsync
处理程序移动到控制器/操作对中,这可以相应地归因于 [Authorize]
。
文档中还有一个相关的GitHub issue:
[Authorize]
过滤器属性自 Razor 页面 2.0 起已受支持,但请注意它适用于页面模型类级别
如果您需要更好的解决方法,请参阅 akbar's answer 和 Jim Yabro's answer。
【讨论】:
【参考方案2】:另一种解决方案是通过 if 子句检查身份验证。像这样:
if (!HttpContext.User.Identity.IsAuthenticated)
return Redirect("/Front/Index");
你也可以通过查找角色来查看roles
:
var user = await _userManager.FindByEmailAsync(model.Email);
var roles = await _userManager.GetRolesAsync(user);
【讨论】:
【参考方案3】:我建议在 ASP.NET Core 中遵循 Razor Pages 授权约定,如下所示:
services.AddRazorPages(options =>
options.Conventions.AuthorizePage("/Contact");
options.Conventions.AuthorizeFolder("/Private");
options.Conventions.AllowAnonymousToPage("/Private/PublicPage");
options.Conventions.AllowAnonymousToFolder("/Private/PublicPages");
);
在您使用策略 test
的情况下,它看起来像这样:
options.Conventions.AuthorizePage("/Account", "test");
来源:
https://docs.microsoft.com/en-us/aspnet/core/security/authorization/razor-pages-authorization?view=aspnetcore-5.0
支持授权属性,但仅限于PageModel
,如下所示:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace PageFilter.Pages
[Authorize]
public class ModelWithAuthFilterModel : PageModel
public IActionResult OnGet() => Page();
来源:
https://docs.microsoft.com/en-us/aspnet/core/razor-pages/filter?view=aspnetcore-5.0#authorize-filter-attribute
【讨论】:
【参考方案4】:不要使用AuthorizeAttribute
,因为它不受支持。
相反,一旦您在 Startup.cs
中配置了您的政策,您就可以在页面处理程序中检查这些政策。
-
将
IAuthorizationService
注入您的页面模型构造函数
在处理程序中调用AuthorizeAsync()
。
对结果的.Succeeded
属性运行条件检查。
如果.Succeeded
为假,则返回Forbid()
结果。
这与[Authorize(Policy=...)]
的结果几乎相同,但在页面生命周期的后期执行。
using Microsoft.AspNetCore.Authorization;
// ...
public class TestPageModel : PageModel
readonly IAuthorizationService AuthorizationService;
public TestPageModel(IAuthorizationService authorizationService)
AuthorizationService= authorizationService;
// Everyone can see this handler.
public void OnGet()
// Everyone can access this handler, but will be rejected after the check.
public async Task<IActionResult> OnPostAsync()
// This is your policy you've defined in Startup.cs
var policyCheck = await AuthorizationService.AuthorizeAsync(User, "test");
// Check the result, and return a forbid result to the user if failed.
if (!policyCheck.Succeeded)
return Forbid();
// ...
return Page(); // Or RedirectToPage etc
【讨论】:
【参考方案5】:我使用Permission-based Authorization in ASP.NET Core 的解决方法:
[Authorize(Permissions.PageX.AddParameter)]
public async Task<IActionResult> OnPostAddParameterAsync(uint id, string key, string value)
if (!this.ArePermissionsValid()) return Forbid();
/// ...
public static class PageExtensions
public static bool ArePermissionsValid(this PageModel page)
try
var authorizeAttribute = new StackTrace().GetFrames().FirstOrDefault(x => x.GetMethod().Name.StartsWith("On")).GetMethod().GetCustomAttribute<AuthorizeAttribute>();
if (authorizeAttribute == null) return true;
var hasPermissions = page.User.Claims.Any(x => x.Type.Equals("permission") && x.Value.Equals(authorizeAttribute.Policy));
return hasPermissions;
catch (Exception e)
Log.Error($"$nameof(PageExtensions).nameof(ArePermissionsValid) | e.Message");
return false;
【讨论】:
以上是关于ASP .NET Core Razor 页面中的授权的主要内容,如果未能解决你的问题,请参考以下文章
更改 ASP.NET Core Razor 页面中的默认登录页面?
将 ASP.NET Core Razor 页面中的默认页面更改为登录页面