写这个的原因

现在BootstrapBlazor处于大更新时期,Menu组件要改为泛型模式。

本来我们的这一篇应该是把Layout改了,但是改Layout肯定要涉及到菜单,如果现在写了呢,就进入一个发布就过时的状态,就很尴尬,所以后面的就稍微拖一拖。

加上昨天有人说我用OnNavigateAsync违反单一性原则,要用策略,所以这里我们说下策略怎么做。

添加策略相关的代码

首先我们要有一个实现IAuthorizationRequirement接口的类,这个类没有什么特别的要求,我们就写一个空类来处理。

public class AdminRequirement : IAuthorizationRequirement
{ }

然后要写一个Handler,来继承这个AuthorizationHandler<AdminRequirement>,其中泛型是我们上面的实现接口的类。

public class AdminRequirementHandler : AuthorizationHandler<AdminRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdminRequirement requirement)
{ context.Succeed(requirement);
return Task.CompletedTask;
}
}

实现HandleRequirementAsync方法,这个方法就是我们的关键方法,授权的实现就在这里面。

其中默认的授权状态是Fail,如果我们希望允许通过,就执行context.Succeed(requirement);来告诉策略我们认证成功了。

添加授权认证

Program.cs里我们需要把这两个都注册进去,首先注册我们的Handler

builder.Services.AddSingleton<IAuthorizationHandler, AdminRequirementHandler>();

然后注册我们的授权策略

builder.Services.AddAuthorization(options =>
{
options.AddPolicy("Admin", policy => policy.Requirements.Add(new AdminRequirement()));
});

这里的Admin就是我们的策略名字。

使用策略

在我们需要认证的位置增加特性@attribute [Authorize(Policy = "Admin")],然后在我们的授权策略里打断点,应该就会发现断点进入了。

将RouteData传入

因为Blazor里面我们拿不到HttpContext,所以没法用Request.Path的方式来拿到url,所以只能使用将RouteData作为Resource传入,然后使用attribute的方式拿到。

这里我们在App.razor里传入routeData

<AuthorizeRouteView Resource="@routeData" RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<RedirectToLogin></RedirectToLogin>
</NotAuthorized>
</AuthorizeRouteView>

然后修改HandleRequirementAsync

if (context.User.Identity?.IsAuthenticated != true)
{
return Task.CompletedTask;
} if (!int.TryParse(context.User.FindFirst(ClaimTypes.Role)?.Value, out var roleId))
{
return Task.CompletedTask;
}
if (context.Resource is RouteData routeData)
{
var routeAttr = routeData.PageType.CustomAttributes.FirstOrDefault(x =>
x.AttributeType == typeof(RouteAttribute));
if (routeAttr == null)
{
context.Succeed(requirement);
}
else
{
var url = routeAttr.ConstructorArguments[0].Value as string;
var permission = PermissionEntity
.Where(x => x.Roles!.Any(y => y.Id == roleId) && x.Url == url).First();
if (permission != null)
{
context.Succeed(requirement);
}
}
} return Task.CompletedTask;
}

这里跟上一篇的处理思路整体一样,首先我们判断如果用户都没登录,那就直接失败,如果登录了我们就去拿RoleId,拿不到自然就失败。

不同点在下面,我们没法直接拿到Path,所以我们只能去找RouteAttribute,其实就是我们的@page路由。这里我们也可以自己定义一个Attribute取自己的。

如果我们没找到这个,证明这应该不是个blazor页面,我们就暂时让它成功。

如果找到了,那么我们就找routeAttr.ConstructorArguments[0].Value as string,这里面就是对应的路由地址了。

下面就跟之前一样,用路由地址来判断是否是又权限就行了。

源码在github: https://github.com/j4587698/BlazorLearn,分支lesson6

从零开始Blazor Server(6)--基于策略的权限验证的更多相关文章

  1. Forms身份验证和基于Role的权限验证

    Forms身份验证和基于Role的权限验证 从Membership到SimpleMembership再到ASP.NET Identity,ASP.NET每一次更换身份验证的组件,都让我更失望.Memb ...

  2. 从零开始Blazor Server(5)--权限验证

    序 之前我们一直使用的是微软自带的身份验证方式,即使用[Authorize]标签来做. 但是这种方式十分不灵活,微软推荐的方式是加Policy,但是这种方式对我们来说还是不够灵活. 所以本节我们用完全 ...

  3. 从零开始Blazor Server(1)--项目搭建

    项目介绍 本次项目准备搭建一个使用Furion框架,Blazor的UI使用BootstrapBlazor.数据库ORM使用Freesql的后台管理系统. 目前的规划是实现简单的注册,登录.增加管理员跟 ...

  4. 从零开始Blazor Server(15)--总结

    我们用了14篇文章,基本上把一个后台管理系统需要的UI部分都说的差不多了.所以这套文章也该到了结束的时候了. 这里面有很多问题,比如我们直接使用UI来拉数据库信息而没有使用service,再比如我们大 ...

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

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

  6. 从零开始Blazor Server(8)--增加菜单以及调整位置

    这篇干啥 这篇文章主要是把前面的一些东西稍微调整一下,使其更适合后面的内容. 主要是两个事,一个是把原来的PermissionEntity直接变成MenuEntity,直接让最后一级是菜单,这样后面就 ...

  7. 从零开始Blazor Server(9)--修改Layout

    目前我们的MainLayout还是默认的,这里我们需要修改为BootstrapBlazor的Layout,并且处理一下菜单. 修改MainLayout BootstrapBlazor已经自带了一个La ...

  8. 从零开始学 Java - Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就 ...

  9. 从壹开始前后端分离 [ vue + .netcore 补程 ] 三十一║ Nuxt终篇:基于Vuex的权限验证探究

    缘起 哈喽大家好,今天周四啦,楼主明天要正式放假了,这里先祝大家节日快乐咯,希望在家里能继续研究点儿东西吧,今天呢是 nuxt 的最后一篇,主要是对权限登录进行研究,这一块咱们之前在说第一个项目的时候 ...

随机推荐

  1. 【多线程】线程同步 synchronized

    由于同一进程的多个线程共享同一块存储空间 , 在带来方便的同时,也带来了访问 冲突问题 , 为了保证数据在方法中被访问时的正确性 , 在访问时加入 锁机制synchronized , 当一个线程获得对 ...

  2. mysqldump速查手册

    一.mysqldump用法 1.1 常见选项 --all-databases, -A: 备份所有数据库 --databases, -B: 用于备份多个数据库,如果没有该选项,mysqldump把第一个 ...

  3. 获取并检查系统负载\CPU\内存\磁盘\网络

    安装依赖 需要net-tools.namp! CentOS:yum -y install net-tools nmap Ubuntu:apt-get update && apt-get ...

  4. 差分隐私(Differential Privacy)定义及其理解

    1 前置知识 本部分只对相关概念做服务于差分隐私介绍的简单介绍,并非细致全面的介绍. 1.1 随机化算法 随机化算法指,对于特定输入,该算法的输出不是固定值,而是服从某一分布. 单纯形(simplex ...

  5. drools决策表的简单使用

    目录 一.背景 二.一个简单的决策表 1.在同一个决策表中处理多个Sheet页 2.RuleSet下方可以有哪些属性 3.RuleTable下方可以有哪些属性 4.规则属性的编写 三.需求 四.实现 ...

  6. 【算法】Floyd算法

    什么是Floyd Floyd用于求最短路程.举个栗子,给你一张图,让你求出点[1]到点[5]的最短路程,你会怎么求? (画图工具:CS Academy) 如上图,有向边分别是 1->2  1-& ...

  7. django框架8

    内容概要 ajax简介 前后端传输数据编码格式 ajax发送json格式数据 ajax携带文件数据 回调机制处理策略 内容详情 ajax简介 页面不刷新的情况下可以与后端进行数据交互 异步提交 局部刷 ...

  8. nvm安装与使用及乱码问题

    前端开发工作中经常负责多个项目(新项目.多年的老项目及团队合作项目),经常会遇到npm install安装依赖包或者启动本地服务时依赖报错的情况,大多数是因为NodeJS和npm与依赖之间版本的问题, ...

  9. 第2章 C++编程入门

    C++中的数据分为常量和变量. 2.1常量(Constants) 顾名思义,常量的值在程序中不能改变 Type of constant(常量数据类型) | integer:整型 | floating- ...

  10. ”只用 1 分钟“ - 超简极速 Apk 签名 & 多渠道打包神器

    众所周知,渠道包作为当下国内 Android 应用市场常见的分发方式,当 APP 和后台交互或进行数据上报时,会带上各自的 channel 渠道信息,以此方便企业 & 开发者统计 APP 在各 ...