原文: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. php实现基础排序算法

    <?php header("content-type:text/html;charset=utf-8"); $testArr = array(); $time1 = micr ...

  2. ZooKeeper安装、配置和使用

    Zookeeper的概述: ZooKeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目. ZooKeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架, ...

  3. Java关键字之abstract、final、static用法

    abstract:即抽象的,可以修饰类.方法: 修饰类:当有一个方法为抽象方法时,这个类就是抽象类,抽象类不能被new,它是一个不完整的类. 修饰方法:这个方法就是抽象的,即只能方法的定义,没有方法的 ...

  4. 性能优化之mybatis实现接口的批量查询,减少数据库的查询消耗

    <select id="selectByTime" resultType="com.neo.xnol.api.activity.dto.ActivityMqmsgD ...

  5. HTML中html元素的lang属性的说明

    HTML中html元素的lang属性的说明 我在刚开始学习HTML的时候,关于基本的HTML格式中有一点不明白的地方,基本格式如下 <!DOCTYPE html> <html lan ...

  6. xml的解析(概述)

    使用java解析xml☆☆☆ 四个类:分别是针对dom和sax解析使用的类   -dom :     DocumentBuilder:解析器类       -这个类是个抽象类,不能new,       ...

  7. 【转载】Gradle for Android 第四篇( 构建变体 )

    当你在开发一个app,通常你会有几个版本.大多数情况是你需要一个开发版本,用来测试app和弄清它的质量,然后还需要一个生产版本.这些版本通常有不同的设置,例如不同的URL地址.更可能的是你可能需要一个 ...

  8. Activit 5.13 工作流部署新版本后回退到上一个版本

    有时因为某些原因Activit流程部署新版本后,还没有发起流程,回退到上一个版本.操作过程: 1.查询版本更新记录,记录字段ID_值,假设值为100: select to_char(t.deploy_ ...

  9. 传入一个Map<String,Long> 返回它按value排序后的结果

    //传入一个Map<String,Long> 返回它按value排序后的结果 sort为正序还是倒序(-1倒序),size为要几条数据 private static Map<Stri ...

  10. Go命令行库Cobra的核心文件root.go

    因为docker及Kubernetes都在用cobra库,所以记录一下. 自定义的地方,高红标出. root.go /* Copyright © 2019 NAME HERE <EMAIL AD ...