之前我们一直使用的是微软自带的身份验证方式,即使用[Authorize]标签来做。

但是这种方式十分不灵活,微软推荐的方式是加Policy,但是这种方式对我们来说还是不够灵活。

所以本节我们用完全自己校验的方式完成权限验证。

OnNavigateAsync介绍

在 App.razor 里面的Router节点,微软给了一个OnNavigateAsync方法,这个方法在每次路由跳转的时候都会执行,所以我们可以把我们的权限验证搬到这里来。

App.razor

首先,我们在Router节点上增加OnNavigateAsync

<Router AppAssembly="@typeof(App).Assembly" OnNavigateAsync="PermissionCheck">

这里我们的方法叫做PermissionCheck

然后我们来看这个PermissionCheck方法。

    private void PermissionCheck(NavigationContext context)
{
var whiteList = Furion.App.Configuration["WhiteList"];
if (whiteList != null && whiteList.Split(',').Contains(context.Path))
{
return;
} var user = Furion.App.User;
if (user == null)
{
NavigationManager.NavigateTo("/Login");
return;
} if (user.Identity?.IsAuthenticated != true)
{
NavigationManager.NavigateTo("/Login");
return;
} if (!int.TryParse(user.FindFirst(ClaimTypes.Role)?.Value, out var roleId))
{
NavigationManager.NavigateTo("/Login");
return;
} var permission = PermissionEntity
.Where(x => x.Roles!.Any(y => y.Id == roleId) && x.Url == context.Path).First(); if (permission == null)
{
NavigationManager.NavigateTo("/Login");
} }

这里我们需要把Login这个页面拿出来,因为我们的Login页面应该是一个白名单页面,无需登录也可以访问,所以我在appsettings.json中增加了一项,为WhiteList,这里面以,分隔,所有在这里面的路径都是白名单路径,可以不用登录直接访问。

"WhiteList": "Login"

这里注意,OnNavigateAsync给的Path是相对路径,不带最前面的/,所以我们的Login也不能有/

这里判断如果是白名单,则直接return,正常跳转。

var user = Furion.App.User;
if (user == null)
{
NavigationManager.NavigateTo("/Login");
return;
} if (user.Identity?.IsAuthenticated != true)
{
NavigationManager.NavigateTo("/Login");
return;
}

然后获取我们的登录信息,如果没有登录,那么直接跳转到Login页面。

if (!int.TryParse(user.FindFirst(ClaimTypes.Role)?.Value, out var roleId))
{
NavigationManager.NavigateTo("/Login");
return;
}

这里获取我们当时在LoginController里的RoleId

这里注意,我稍微改了一下,之前的文章里我们这里面放的是RoleName,本来是打算根据用户再获取权限,但是后来想想有点麻烦,就稍微改动了一下,具体的可以看下新的源码。实战中建议还是不要直接放RoleId进去,因为这个玩意在实战中往往是一对多的。

var permission = PermissionEntity
.Where(x => x.Roles!.Any(y => y.Id == roleId) && x.Url == context.Path).First(); if (permission == null)
{
NavigationManager.NavigateTo("/Login");
}

最后我们判断一下数据库里这个角色有没有这个路径的权限,如果没有,我们就跳转。

这样我们就可以实现根据path来判断权限了。

这里由于是教程类的,所以所有的判断我都是直接从数据库里取得,正式使用的时候建议放到缓存里面,如果没有页面都走一次数据库,那么数据库的压力会非常大。

默认数据的路径我稍微修改了一下,去掉了前面的/,这里直接把数据库给删掉,然后重新运行就行了。

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

从零开始Blazor Server(5)--权限验证的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 从零开始Blazor Server(6)--基于策略的权限验证

    写这个的原因 现在BootstrapBlazor处于大更新时期,Menu组件要改为泛型模式. 本来我们的这一篇应该是把Layout改了,但是改Layout肯定要涉及到菜单,如果现在写了呢,就进入一个发 ...

  7. 从零开始Blazor Server(7)--使用Furion权限验证

    序 上面两篇我们讲了怎么用OnNavigateAsync来验证权限,又写了怎么用策略来验证权限. 其实我们既然集成了Fution,就可以用Furion带的方式来验证. 创建AdminHandler 我 ...

  8. 从零开始Blazor Server(2)--整合数据库

    开篇 上一篇文章我们留了个尾巴,没有把freesql整合进去,这篇文章我们来整合. 目前的思路呢,是做一个简单的四不像的RABC,也有用户.角色. 权限三部分. 但是其中每个用户只有一个角色,即用户和 ...

  9. 从零开始Blazor Server(4)--登录系统

    说明 上一篇文章中我们添加了Cookie授权,可以跳转到登录页了.但是并没有完成登录,今天我们来完成它. 我们添加Cookie授权的时候也说了,这套跟MVC一模一样,所以我们登录也是跟MVC一模一样. ...

随机推荐

  1. 『忘了再学』Shell基础 — 13、环境变量(一)

    目录 1.用户自定义的环境变量 (1)环境变量设置 (2)查询自定义环境变量 (3)删除自定义环境变量 2.系统自带的环境变量--PATH环境变量 (1)PATH环境变量 (2)PATH环境变量的作用 ...

  2. linux篇-centos7安装samba服务器

    1查看是否安装samba服务 2如果为空则没有安装,安装显示安装完成即成功 3查看samba状态 4查看配置文件的位置 5配置文件备份,直接传输到本地备份 6修改配置文件 Path共享目录位置 Val ...

  3. unity---公共模块MonoController

    公共模块 如果有很多类使用Update()函数,会导致性能浪费 如果函数统一在一个Update()中执行 代码 上述,需要将脚本挂载到物体上, 故新建了一个管理类MonoMgr Mgr另外的作用 可以 ...

  4. 记 iTextSharp 剪裁 PDF 指定区域的方法

    原文 引用 itextsharp 5.5.13.2 itextsharp.xtra 5.5.13.2 方法 /// <summary> /// 截取pdf文件,例如把A4截出指定的A6区域 ...

  5. C++从静态类型到单例模式

    目录 1. 概述 2. 详论 2.1. 静态类型 2.1.1. 静态方法成员 2.1.2. 静态数据成员 2.2. 单例模式 2.2.1. 实现 2.2.2. 问题 3. 参考 1. 概述 很多的知识 ...

  6. 聊聊OOP中的设计原则以及访问者模式

    一  设计原则 (SOLID) 1.  S - 单一职责原则(Single Responsibllity Principle) 1.1  定义 一个类或者模块只负责完成一个职责(或功能), 认为&qu ...

  7. markdown常用到的语法

    一.标题 后加文字,几个#代表几级标题,最高为6 ,标准语法一般在#后跟个空格再写文字. 二.分割线 三个或者三个以上的 - 或者 * 三.图片 格式: ![A](B "C") A ...

  8. 全新升级的AOP框架Dora.Interception[1]: 编程体验

    多年之前利用IL Emit写了一个名为Dora.Interception(github地址,觉得不错不妨给一颗星)的AOP框架.前几天利用Roslyn的Source Generator对自己为公司写的 ...

  9. JS:undefined number

    undefined数据类型:未定义属性 undefined 表示不含值 <script> var t1=""; var t2; if (t1===undefined) ...

  10. 实测:云RDS MySQL性能是自建的1.6倍

    1. 摘要 基于之前写的「云厂商 RDS MySQL 怎么选」的文章,为了进一步了解各云厂商在RDS MySQL数据库性能上的差异,本文将对自建MySQL.阿里云.腾讯云.华为云和AWS 的 RDS ...