Blazor 下支持 Azure AD 的多套登录方案

比如上图配置了两套不同的登录方案,各有自己的 TenantId 和 ClientId ,要同时支持他们的登录(其实在同一套 TenantId 和 ClientId 里面配置多个登录账户不就好了,但是......那套登录的管理是在客户自己的Azure AD账户管理下的,而作为技术支持不想麻烦客户,更何况客户不一定同意呢,所以需要第二套专为技术支持提供的用户组......那么就自己再弄一套吧)

然后问题就来了,在Blazor 页面要触发验证需要调用 HttpContext.ChallengeAsync,你可以试试在.razor 组件内调用 HttpContextAccessor.HttpContext.ChallengeAsync 会发生什么......
当你执行的时候,由于Blazor 使用的是 WebSocket 所以这个 Http 的处理方式就报错了,说你的请求头有问题,是不是很无语?

那么怎么解决这个问题呢?在Asp.net Core 3.0 就加入了 EndPoints 终结点的概念,看一下 ChatGPT 是怎么说的

由此看来 EndPoints 可以自定义的控制路由访问,比Controller更加强大

所以这个时候搞明白一件事情,对于多个 oidc 的登录,需要自己用一特定路由地址来实现

这个工作都在 StartUp 里完成,只列出核心代码

1. 注册两套 OIDC 登录方案,注意他们的 CallbackPath  不能是一样的

        public void ConfigureServices(IServiceCollection services){......services.AddRazorPages();services.AddServerSideBlazor();// Configure authenticationvar authorityFormat = Configuration["AzureAd:Authority"];var callbackPath = Configuration["AzureAd:CallbackPath"];services.AddAuthentication(options =>{options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;}).AddCookie().AddOpenIdConnect(_customerAuthType, options =>{options.Authority = string.Format(CultureInfo.InvariantCulture, authorityFormat, Configuration[$"AzureAd:{_customerAuthType}:TenantId"]);options.ClientId = Configuration[$"AzureAd:{_customerAuthType}:ClientId"];options.CallbackPath = Configuration[$"AzureAd:{_customerAuthType}:CallbackPath"];options.ResponseType = OpenIdConnectResponseType.IdToken; // Use implicit flowoptions.Scope.Add("openid");options.Scope.Add("profile");options.Events = new OpenIdConnectEvents{OnTokenValidated = context =>{var identity = context.Principal.Identity as ClaimsIdentity;identity.AddClaim(new Claim(_authScheme, _customerAuthType));return Task.CompletedTask;}};}).AddOpenIdConnect(_supportAgentAuthType, options =>{options.Authority = string.Format(CultureInfo.InvariantCulture, authorityFormat, Configuration[$"AzureAd:{_supportAgentAuthType}:TenantId"]);options.ClientId = Configuration[$"AzureAd:{_supportAgentAuthType}:ClientId"];                                options.CallbackPath = Configuration[$"AzureAd:{_supportAgentAuthType}:CallbackPath"];                options.ResponseType = OpenIdConnectResponseType.IdToken;options.Scope.Add("openid");options.Scope.Add("profile");options.Events = new OpenIdConnectEvents{OnTokenValidated = context =>{var identity = context.Principal.Identity as ClaimsIdentity;identity.AddClaim(new Claim(_authScheme, _supportAgentAuthType));return Task.CompletedTask;}};});services.AddAuthorization();......}

2. 使用 Endpoints 响应自己定义的路由处理 (登录和登出)

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env){......app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();endpoints.MapBlazorHub();endpoints.MapFallbackToPage("/_Host");// Add endpoints for login challengesendpoints.MapGet("/login-customer", async context =>{await context.ChallengeAsync(_customerAuthType, new AuthenticationProperties{RedirectUri = "/"});});endpoints.MapGet("/login-support-agent", async context =>{await context.ChallengeAsync(_supportAgentAuthType, new AuthenticationProperties{RedirectUri = "/"});});// Add endpoint for logoutendpoints.MapGet("/logout", async context =>{var user = context.User;if (user.Identity.IsAuthenticated){var authSchemeClaim = user.FindFirst(_authScheme);if (authSchemeClaim != null){var authScheme = authSchemeClaim.Value;var tenant = user.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value;await context.SignOutAsync(authScheme);// sign out from IDPif (tenant != null){// Construct the current full URL                                var currentUrl = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.PathBase}";context.Response.Redirect($"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/logout?post_logout_redirect_uri={currentUrl}");}}}await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);                    });});}

可以看到上面分别注册了三个路由 /login-customer,/login-support-agent,/logout

一个给客户登录用,一个给技术支持登录用,最后一个是登出,

这个时候再利用 HttpContext 去 Challenge 就不会报错了,那么 blazor 页面上所做就是跳转到上面的路由地址就可以实现相应的登录和登出了

    private void SupportAgentLogin(){navigation.NavigateTo("/login-support-agent", true);}private void Logout(){navigation.NavigateTo("/logout", true);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/14159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot3 解决NoResourceFoundException: No static resource favicon.ico.异常

SpringBoot3 解决NoResourceFoundException: No static resource favicon.ico.异常 spring boot3项目中浏览器中访问报错找不到favicon.ico,虽然不影响使用,用api工具也可以忽略这个异常,但是防止浏览器访问时出现异常干扰日志,所…

oracle数据库解析过高分析

解析非常高,通过时间模型可以看到解析占比非常高 解析大致可以分为硬解析( hard parse)、软解析( soft parse)和软软解析( soft soft parse)。如,执行一条 SQL 的时候,如…

星型模型和雪花模型的区别

星型模型和雪花模型都是数据仓库设计中常用的维度建模方法,它们之间的主要区别在于数据组织结构、数据冗余度、查询效率、可扩展性和正规化程度等方面: 星型模型 结构特点:星型模型中,一个中心的事实表连接多个维度表&#xff0…

在电脑中,Apple Mobile Device Support程序是什么?

Apple Mobile Device Support 是一项关键的后台服务,它为 Windows 用户提供了与苹果 iOS 设备(包括 iPhone、iPad 和 iPod)顺畅互动的能力。这项服务的核心功能是为iTunes软件提供必要的支持,使得用户能够将他们的移动设备与电脑连…

Google Find My Device:科技守护,安心无忧

在数字化的时代,我们的生活与各种智能设备紧密相连。而 Google Find My Device 便是一款为我们提供安心保障的实用工具。 一、Find My Decice Netword的定义 谷歌的Find My Device Netword旨在通过利用Android设备的众包网络的力量,帮助用户安全的定位所…

HTML5 历史、地理位置处理、全屏处理

目录 历史HistoryAPI地理位置处理GeolocationAPI全屏处理FullscreenAPIHistoryAPI window.history 对象 window.history 是浏览器提供的一个内置对象,它提供了对浏览器历史记录的访问和操作能力。通过这个对象,开发者可以实现无刷新页面跳转、添加新的浏览历史条目等,从而提…

STM32F4_HAL控制GPIO输出——跑马灯实验

1、GPIO工作模式 1.1 端口输入数据寄存器(IDR) 1.2 端口输出数据寄存器(ODR) 1.3 端口置位/复位寄存器(BSRR) 为什么有了 ODR 寄存器,还要这个 BSRR 寄存器呢?我们先看看 BSRR 的寄…

23种设计模式(持续输出中)

一.设计模式的作用 设计模式是软件从业人员长期总结出来用于解决特定问题的通用性框架,它提高了代码的可维护性、可扩展性、可读性以及复用性。 二.设计模式 1.工厂模式 工厂模式提供了创建对象的接口,而无需制定创建对象的具体类,工厂类…

hive表在HDFS的每个文件的大小加大

配置参数: spark.hadoop.hive.exec.orc.default.stripe.size78643200 spark.hadoop.orc.stripe.size78643200 spark.hadoopRDD.targetBytesInPartition78643200 spark.hadoop.hive.exec.dynamic.partition.modenonstrict spark.sql.sources.partitionOverwriteMode…

华为OD机试 - 剩余银饰的重量(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试…

【Python】 如何对对象列表进行排序,有点意思

在Python中,我们经常需要对对象列表进行排序,这可以通过多种方式实现。当对象是一个自定义类实例时,排序通常基于对象的一个或多个属性。Python提供了内置的sorted()函数和列表的sort()方法,它们都允许我们指定一个排序的关键字。…

iPhone彻底删除的照片怎么恢复?专业技巧助您解忧

在使用iPhone的过程中,我们可能会因为误操作或其他原因将一些重要的照片彻底删除。然而,即使照片被彻底删除,也并不意味着它们就永远消失了,它们只是被打上了“可覆盖的空间”的标签。 在照片被新数据覆盖之前,我们仍…

C语言学习【C控制语句:循环】

C语言学习【C控制语句:循环】 while循环 /* 根据用户键入的整数求和 */#include "stdio.h"int main(void) {long num;long sum 0L; /* 把sum初始化为0 */int status;printf("Please enter an integer to be summed");printf(&quo…

基于微信小程序的校园捐赠系统的设计与实现

校园捐赠系统是一种便捷的平台,为校园内的各种慈善活动提供支持和便利。通过该系统,学生、教职员工和校友可以方便地进行捐赠,并了解到相关的项目信息和捐助情况。本文将介绍一个基于Java后端和MySQL数据库的校园捐赠系统的设计与实现。 技术…

Java日期Date和LocalDateTime的工具类

Date package com.qiangesoft.utils.date;import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;/*** 日期工具类** author lq* date 2024-05-23*/ public class DateUtil {public static final String[] CHINESE_WEEK_DAY new String[]{&q…

Excel 公式积累

1.获取当前位置的左侧单元格 引用当前单元格左侧的第一个单元格:OFFSET(INDIRECT(ADDRESS(ROW(), COLUMN())),0,-1) ROW()返回当前单元格的行号,COLUMN()返回当前单元格的列号。 ADDRESS函数可以根据指定行号和列号获得工作表中的某个单元格的地址。例如…

go全部版本下载目录

linux安装教程: Download and install - The Go Programming Language rm -rf /usr/local/go && tar -C /usr/local -xzf go1.22.3.linux-amd64.tar.gzexport PATH$PATH:/usr/local/go/bin go version 全部版本下载目录: All releases - Th…

鸿蒙本机通信

demo地址 https://github.com/MartinLi89/WanHarmony 目前只学到一部分,不正确的地方,还望大家指正,我会及时更新,谢谢,欢迎评论留言 线程内通信,线程间通信,进程间通信 本篇帖子中描述的比较宽…

快速开发 Chrome插件

什么是 Chrome 插件 Chrome 插件程序是一种用于增强 Google Chrome 浏览器功能的小型软件应用程序。它们可以帮助用户自定义浏览体验、添加新功能、集成外部服务以及自动化任务等。扩展程序使用 HTML、CSS 和 JavaScript 编写,利用 Chrome 提供的 API 来与浏览器及…

18.分布式监控zabbix-proxy

zabbix proxy 使用场景: 监控远程区域设备监控本地网络不稳定区域当 zabbix 监控上千设备时,使用它来减轻 server 的压力简化分布式监控的维护 环境规划: zabbix-server:外网IP地址192.168.111.66 zabbix-proxy:外网IP地址192.168.111.11 内网IP地址…