原文:https://chrissainty.com/securing-your-blazor-apps-configuring-policy-based-authorization-with-blazor/

上一篇文章中,我展示了如何向Blazor WebAssembly(Blazor客户端)应用程序添加基于角色的授权。在这篇文章中,我将向您展示如何使用Blazor配置基于策略的授权。

基于策略的授权

ASP.NET Core基于策略的授权允许一种更加灵活的方式来创建授权规则。策略授权由三个概念组成:

  • Policy - 策略有一个或者多个要求。
  • Requirement - 策略用于评估当前用户主体的数据参数集合。
  • Handler - 处理程序用于确定当前用户主体是否有权访问所请求的资源。

策略通常在应用程序启动时在Startup类的ConfigureService方法中注册。

            services.AddAuthorization(config => {
config.AddPolicy("IsDeveloper", policy => policy.RequireClaim("IsDeveloper", "true"));
});

在上面的示例中,策略IsDeveloper要求用户需要有IsDeveloper声明,并且值为true

与角色授权一样,您一样可以使用Authorize属性应用于策略授权。

[Route("api/[controller]")]
[ApiController]
public class SystemController
{
[Authorize(Policy = “IsDeveloper”)]
public IActionResult LoadDebugInfo()
{
// ...
}
}

Blazors指令和组件也一样可以使用策略。

@page "/debug"
@attribute [Authorize(Policy = "IsDeveloper")]
<AuthorizeView Policy="IsDeveloper">
<p>You can only see this if you satisfy the IsDeveloper policy.</p>
</AuthorizeView>

更容易管理

基于策略的授权的最大优点就是改进应用程序中的授权管理。使用基于角色的授权,如果我们有两个角色被允许访问受保护资源 - 比如adminmoderator。我们需要在每个被允许的访问的资源添加一个Authorize属性。

[Authorize(Roles = "admin,moderator")]

这在一开始看起来不是很糟糕,但是如果出现一个新的需求,第三个角色superuser,需要相同的访问权限,该怎么办呢?现在我们需要在每个被访问资源更新所有角色。通过基于策略的验证,我们可以避免这种情况。

我们可以在一个定义一个策略,然后将其应用于需要它的所有资源。当需要添加额外角色时,我们只需更新这个策略,而不需要更新各个资源。

public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(config =>
{
config.AddPolicy("IsAdmin", policy => policy.RequireRole("admin", "moderator", "superuser"));
});
}
[Authorize(Policy = "IsAdmin")]

创建自定义需求

策略授权非常灵活,您可以基于角色、声明创建需求,甚至可以创建自定义需求。让我们来看看如何创建自定义需求。

通常,当您有复杂的逻辑时,会使用自定义需求。如上所述,我们需要顶一个需求和一个处理程序来使用策略授权。

我们来创建一个检查用户的电子邮件地址是否使用公司域的需求。我们需要创建授权需求类,这个类需要实现IAuthorizationRequirement接口,这只是一个空的标记接口。

public class CompanyDomainRequirement : IAuthorizationRequirement
{
public string CompanyDomain { get; } public CompanyDomainRequirement(string companyDomain)
{
CompanyDomain = companyDomain;
}
}

接下来,我们需要为我们的需求创建一个继承自AuthorizationHandler的处理程序,T就是要处理的需求。

public class CompanyDomainHandler : AuthorizationHandler<CompanyDomainRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CompanyDomainRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.Email))
{
return Task.CompletedTask;
} var emailAddress = context.User.FindFirst(c => c.Type == ClaimTypes.Email).Value; if (emailAddress.EndsWith(requirement.CompanyDomain))
{
return context.Succeed(requirement);
} return Task.CompletedTask;
}
}

在上面代码中,我们检查是否存在电子邮件声明。如果存在,那么我们检查它是否按要求中指定的域结束,如果是,则返回成功,否则就是失败。

我们只需要将我们的要求与一个策略关联起来,并将CompanyDomainHandler注册到依赖注入容器中。

public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(config =>
{
config.AddPolicy("IsCompanyUser", policy =>
policy.Requirements.Add(new CompanyDomainRequirement("newco.com")));
}); services.AddSingleton<IAuthorizationHandler, CompanyDomainHandler>();
}

要了解更多关于自定义要求的详细信息,建议查看官方文档

Blazor中使用策略

现在我们已经了解了什么是策略,让我们看看如何在应用程序中使用它们。

我们将把上一篇文章的中Blazor应用程序切换到基于策略的授权。作为这项工作的一部分,我们将看到基于策略的授权的另一个优点,即能够在共享项目中定义策略并在服务端和客户端引用它们。

创建共享策略

在share项目中创建策略之前,我们需要先从NuGet安装Microsoft.AspNetCore.Authorization这个包。

安装之后,使用以下代码创建一个名为Policies 的类。

    public static class Policies
{
public const string IsAdmin = "IsAdmin";
public const string IsUser = "IsUser"; public static AuthorizationPolicy IsAdminPolicy() {
return new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
.RequireRole("Admin")
.Build();
} public static AuthorizationPolicy IsUserPolicy() {
return new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
.RequireRole("User")
.Build();
}
}

我们首先定义了两个常量IsAdminIsUser。我们将在注册策略时候使用它们。接下来是策略本身,IsAdminPolicyIsUserPolicy。这里我使用AuthorizationPolicyBuilder来定义每个策略,这两个策略都需要用户进行身份验证,然后根据策略的不同,用户可以是Admin角色和User角色。

配置服务端

现在我们已经定义了策略,我们需要让服务端使用它们。首先,在Startup类中的ConfigureServices方法注册策略,在AddAuthentication之后添加以下代码。

            services.AddAuthorization(config => {
config.AddPolicy(Policies.IsAdmin, Policies.IsAdminPolicy());
config.AddPolicy(Policies.IsUser, Policies.IsUserPolicy());
});

代码非常容易理解,我们使用Policies类中定义的常量来声明它们的名称,并注册每个策略,避免使用魔法字符串。

WeatherForecastController则可以使用IsAdmin策略代旧的角色。

    [ApiController]
[Route("[controller]")]
[Authorize(Policy = Policies.IsAdmin)]
public class WeatherForecastController : ControllerBase

同样,我们可以使用名称常量来避免魔法字符串。

配置客户端

现在服务端可以使用我们定义的新策略,接下来就是在Blazor客户端使用他们。

和服务端一样,我们也在在Startup类中的ConfigureServices方法注册策略。之前我们已经调用了AddAuthorizationCore,所以只需要更新它。

            services.AddAuthorizationCore(config => {
config.AddPolicy(Policies.IsAdmin, Policies.IsAdminPolicy());
config.AddPolicy(Policies.IsUser, Policies.IsUserPolicy());
});

Index.razor,使用策略更新AuthorizeView组件 - 一样要避免使用魔法字符串。

<AuthorizeView Policy="@Policies.IsUser">
<p>You can only see this if you satisfy the IsUser policy.</p>
</AuthorizeView> <AuthorizeView Policy="@Policies.IsAdmin">
<p>You can only see this if you satisfy the IsAdmin policy.</p>
</AuthorizeView>

最后,更新FetchData.razorAuthorize属性。

@attribute [Authorize(Policy = Policies.IsAdmin)]

就是这样!我们的应用程序现在转移到基于策略的授权。我们现在有一个更灵活的授权系统,可以使用角色、声明、自定义策略或者上述任何组合。

关于服务端Blazor

我并没有专门讨论服务端Blazor,原因很简单,我们上面所做的应该可以毫无问题的转移到服务端Blazor。

总结

在这篇文章中,我们讨论了ASP.NET Core和Blazor基于策略的授权。我们也了解了使用基于策略的授权相对于基于角色的授权的一些优点并且我们将应用程序从基于角色的验证迁移到了基于策略的验证。

最后还是代码(GITHUB)

Blazor应用程序基于策略的授权的更多相关文章

  1. Blazor应用程序基于角色的授权

    原文:https://chrissainty.com/securing-your-blazor-apps-configuring-role-based-authorization-with-clien ...

  2. Security » Authorization » 基于自定义策略的授权

    Custom Policy-Based Authorization¶ 基于自定义策略的授权 98 of 108 people found this helpful Underneath the cov ...

  3. 从零开始Blazor Server(3)--添加cookie授权

    认证方式简述 Blazor Server微软官方还是推荐直接使用Cookie授权,因为本来Blazor Server就是前后端不分离的.不存在Cookie跨域等一系列问题. 只要不是使用SSO之类的统 ...

  4. Asp.Net Core--自定义基于策略的授权

    翻译如下: 在封面下,角色授权和声明授权使用需求,需求的处理程序和预配置的策略. 这些构建块允许您在代码中表示授权评估,从而允许更丰富,可重用和容易测试的授权结构. 授权策略由一个或多个需求组成,并在 ...

  5. shiro认证策略,授权

    有具体问题的可以参考之前的关于shiro的博文,关于shiro的博文均是一次工程的内容 ! 认证策略: 修改认证策略: applicationContext.xml <!-- 认证器 --> ...

  6. Identity Server 4 原理和实战(完结)_Hybrid Flow 实例, Claims, 角色授权和策略授权

    4分50 建立客户端 不需要身份认证 客户端叫做HybirdClient 配置IdentityServer服务端,先把客户端添加上 把userClaims添加到token里面 然后运行服务端就可以了 ...

  7. Linux环境下MySQL的安装、密码策略、忘记密码后的破解及用户授权等。

    mysql安装.用户密码.密码策略.授权用户等(mysql5.7版本) 1.mysql安装后相关目录与文件: 主配置文件: /etc/my.cnf 数据库目录: /var/lib/mysql/ 默认端 ...

  8. 基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化

    最近花了一点时间,阅读了IdentityServer的源码,大致了解项目整体的抽象思维.面向对象的重要性; 生产环境如果要使用 IdentityServer3 ,主要涉及授权服务,资源服务的部署负载的 ...

  9. ASP.NET Core 认证与授权[5]:初识授权

    经过前面几章的姗姗学步,我们了解了在 ASP.NET Core 中是如何认证的,终于来到了授权阶段.在认证阶段我们通过用户令牌获取到用户的Claims,而授权便是对这些的Claims的验证,如:是否拥 ...

随机推荐

  1. C#中对文件进行选择对话框打开和保存对话框进行复制

    场景 通过文件选择对话框选择文件 复制文件到指定路径 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号霸道的程序猿获取编程相关电子书.教 ...

  2. CSS3 盒模型---css初始化会用到:box-sizing: border-box 盒子大小为 width 就是说 padding 和 border 是包含到width里面的

    CSS3中可以通过box-sizing 来指定盒模型,即可指定为content-box.border-box,这样我们计算盒子大小的方式就发生了改变. 可以分成两种情况: 1.box-sizing: ...

  3. js中的作用域

    作用域:      域:空间.范围.区域…… 作用:读.写 浏览器:“JS解析器” 1)“找一些东西” :var  function 参数 a = ...未定义所有的变量,在正式运行代码之前,都提前 ...

  4. .net连接Oracle

    通过网上了解到.net连接Oracle主要有3种方法.(1)System.Data.OracleClient微软的System.Data.OracleClient可以直接引用,但是VS会提示“Syst ...

  5. [转]Oracle 11g RAC SCAN ip的原理及配置

    原文地址:http://tiany.blog.51cto.com/513694/1421917/ Oracle 11g RAC SCAN ip的原理及配置   Oracle 11g RAC网格即插即用 ...

  6. 测试文档(final)

    1 引言 1.1编写目的 编写本测试计划的目的是: (1)     为整个测试阶段的管理工作和技术工作提供指南同时确定测试的内容和范围,为评价系统提供依据: (2)     此外还帮助安排测试活动,说 ...

  7. Zeppelie连接jdbc的使用

    1. 下载 wget http://apache.mirror.cdnetworks.com/zeppelin/zeppelin-0.8.1/zeppelin-0.8.1-bin-all.tgz 2. ...

  8. TICK技术栈(一)TICK技术栈介绍

    1.什么是TICK技术栈? 1.1 简介 TICK 是由 InfluxData开发的一套开源工具栈,由 Telegraf, InfluxDB, Chronograf, Kapacitor 四个工具的首 ...

  9. express 将 Router 实例模块化

    为了更好的组织代码,将 Router 实例进行模块化,将 get / post 等快捷方式放在Router上,而不是 App 上,然后将该 Router 作为中间件,use 到 server.js 上 ...

  10. Python的 Datetime 、 Logging 模块

    Datetime模块 datetime是python处理时间和日期的标准库 类名 date类        日期对象,常用的属性有 year . month . day time类        时间 ...