原文: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. java基础第十六篇之多线程

    1:线程的概念 进程(任务):一个正在运行的程序 进程的调度:CPU来决定什么时候该运行哪个进程 (时间片轮流法) 线程在一个应用程序中,同时,有多个不同的执行路径,是进程中的实际运作单位. 好处是提 ...

  2. Define the Data Model and Set the Initial Data 定义数据模型并设置初始数据

    This topic describes how to define the business model and the business logic for WinForms and ASP.NE ...

  3. 五个常用的CSS简写

    1,margin/padding. (演示仅为margin,padding同理,需注意的是padding没有auto) 2.background. background: [background-co ...

  4. 异步和多线程Thread

    刚接触线程的时候,感觉这个东西好神奇.虽然不是很明白,就感觉它很牛逼. 参考了一些大佬写的文章: https://www.cnblogs.com/yilezhu/p/10555849.html这个大佬 ...

  5. java中字符串String、StringBuilder、StringBuffer的常用方法

    String的常用方法: public static void main(String[] args) { String str = "Hello world!"; // 获取字符 ...

  6. 8.JavaCC官方入门指南-例3

    例3:计算器-double类型加法   下面我们对上个例子的代码进行进一步的修改,使得代码具有简单的四则运算的功能.   第一步修改,我们将打印出每一行的值,使得计算器更具交互性.一开始,我们只是把数 ...

  7. mysql常见错误代码解释

    mysql常见错误代码解释 原创 作者:bayaim 时间:2017-12-26 11:07:14 38  ---------------------------------------------- ...

  8. Linux(一)-- Linux环境搭建

    Linux环境搭建 一.虚拟机安装 1.下载地址 https://my.vmware.com/web/vmware/info/slug/desktop_end_user_computing/vmwar ...

  9. Python正则表达式中re.S作用

    re.S的作用: 不使用re.S时,则只在每一行内进行匹配,如果存在一行没有,就换下一行重新开始,使用re.S参数以后,正则表达式会将这个字符串看做整体,在整体中进行匹配 对比输出结果: import ...

  10. 关于tomcat的环境参数配置

    在linux里 export CATALINA_OPTS=”-Xms(min heap)m -Xmx(max heap)m” 修改堆内存: -XX:MaxPermSize=128m 修改最大持久带内存 ...