从零开始Blazor Server(6)--基于策略的权限验证
写这个的原因
现在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)--基于策略的权限验证的更多相关文章
- Forms身份验证和基于Role的权限验证
Forms身份验证和基于Role的权限验证 从Membership到SimpleMembership再到ASP.NET Identity,ASP.NET每一次更换身份验证的组件,都让我更失望.Memb ...
- 从零开始Blazor Server(5)--权限验证
序 之前我们一直使用的是微软自带的身份验证方式,即使用[Authorize]标签来做. 但是这种方式十分不灵活,微软推荐的方式是加Policy,但是这种方式对我们来说还是不够灵活. 所以本节我们用完全 ...
- 从零开始Blazor Server(1)--项目搭建
项目介绍 本次项目准备搭建一个使用Furion框架,Blazor的UI使用BootstrapBlazor.数据库ORM使用Freesql的后台管理系统. 目前的规划是实现简单的注册,登录.增加管理员跟 ...
- 从零开始Blazor Server(15)--总结
我们用了14篇文章,基本上把一个后台管理系统需要的UI部分都说的差不多了.所以这套文章也该到了结束的时候了. 这里面有很多问题,比如我们直接使用UI来拉数据库信息而没有使用service,再比如我们大 ...
- 从零开始Blazor Server(3)--添加cookie授权
认证方式简述 Blazor Server微软官方还是推荐直接使用Cookie授权,因为本来Blazor Server就是前后端不分离的.不存在Cookie跨域等一系列问题. 只要不是使用SSO之类的统 ...
- 从零开始Blazor Server(8)--增加菜单以及调整位置
这篇干啥 这篇文章主要是把前面的一些东西稍微调整一下,使其更适合后面的内容. 主要是两个事,一个是把原来的PermissionEntity直接变成MenuEntity,直接让最后一级是菜单,这样后面就 ...
- 从零开始Blazor Server(9)--修改Layout
目前我们的MainLayout还是默认的,这里我们需要修改为BootstrapBlazor的Layout,并且处理一下菜单. 修改MainLayout BootstrapBlazor已经自带了一个La ...
- 从零开始学 Java - Spring AOP 实现用户权限验证
每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就 ...
- 从壹开始前后端分离 [ vue + .netcore 补程 ] 三十一║ Nuxt终篇:基于Vuex的权限验证探究
缘起 哈喽大家好,今天周四啦,楼主明天要正式放假了,这里先祝大家节日快乐咯,希望在家里能继续研究点儿东西吧,今天呢是 nuxt 的最后一篇,主要是对权限登录进行研究,这一块咱们之前在说第一个项目的时候 ...
随机推荐
- 使用RoslynSyntaxTool工具互相转换C#代码与语法树代码
项目地址 MatoApps/RoslynSyntaxTool: 此工具能将C#代码,转换成使用语法工厂构造器(SyntaxFactory)生成等效语法树代码 (github.com) 基础概念 S ...
- MySQL数据库和Oracle数据库的区别
Mysql数据库 由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司.是一种中小型的关系型数据库. MySQL 数据库体积小.速度快.总体拥有成本低.开放源代码,其有着广泛的应用,一般中 ...
- 浅谈倍增法求解LCA
Luogu P3379 最近公共祖先 原题展现 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入格式 第一行包含三个正整数 \(N,M,S\),分别表示树的结点个数.询问 ...
- php为图片添加水印
<?php /** * 图片加水印(适用于png/jpg/gif格式) * * @author flynetcn * * @param $srcImg 原图片 * @param $waterIm ...
- vue大型电商项目尚品汇(后台篇)day04
昨天太晚就没来得及更新,今天是spu管理界面,这个界面一共有三个界面需要切换,完成了两个界面,而且今天的难度在于最后两个章节,富有一定的逻辑性,当然中间也有很多需要注意的,比如ElementUI的照片 ...
- 【Redis】事件驱动框架源码分析(单线程)
aeEventLoop初始化 在server.c文件的initServer函数中,对aeEventLoop进行了初始化: 调用aeCreateEventLoop函数创建aeEventLoop结构体,对 ...
- JavaGUI——Java图形用户界面
1.Java GUI 概述 GUI(Graphical User Interface,简称 GUI,图形用户界面)是指采用图形方式显示的计算机操作用户界面,与早期计算机使用的命令行界面相比,图形界面对 ...
- Kubebuilder模块
CRD创建 Group表示CRD所属的组,它可以支持多种不同版本.不同类型的资源构建,Version表示CRD的版本号,Kind表示CRD的类型 kubebuilder create api --gr ...
- ShardingSphere-proxy-5.0.0建立mysql读写分离的连接(六)
一.修改配置文件config-sharding.yaml,并重启服务 # # Licensed to the Apache Software Foundation (ASF) under one or ...
- LVGL库入门教程 - 动画
动画可以说是 LVGL 中的特色之一,不过在使用动画前,请确保单片机具有足够的性能来维持足够的帧率. transition:过渡动画 当一个控件的状态发生改变时,可以让样式也发生变化以提醒用户.通过过 ...