如何使用 Azure Active Directory 认证和 Microsoft Graph 构建 Blazor Web 应用
如何使用 Azure Active Directory 认证和 Microsoft Graph 构建 Blazor Web 应用
如果您是一个 .NET 开发者,你很可能听过过 Blazor 是一个最近的热门开发技术。Blazor 是一个使用 .NET Blazor 服务器来构建可交互客户端 Web 界面的框架。就是本文所专注的技术,提供了在 ASP.NET Core 应用中,在服务器端寄宿 Razor 组件的支持。UI 的更新通过 SignalR 连接进行。由于多数的应用都需要某些程度的验证和授权,这里将展示如何使用 Azure AD 实现验证的最佳方式,以及如何从 Microsoft Graph 获取数据。
先决条件
为了继续下面的演练,您需要最新版本的 NET Core 3.1 SDK, Visual Studio 2019 (可选,但是最好),并且拥有一个 Azure AD 的租户。如果你不能访问 Azure AD 租户,要么你可以免费注册一个 Microsoft 365 Developer program,或者创建一个免费的 Free Azure Trial 试用账号。
Blazor 与验证
如果你正在构建 Blazor (服务器端) 应用,那么我们有一些好消息。Visual Studio 和 CLI 模版支持开箱即用的验证支持。打开 Visual Studio,然后创建一个新的 Blazor 应用。我们将它命名为 "BlazorAppWithAuth",然后按照下面的动画进行。
通过选择工作或者学校账号验证选项,Visual Studio 将在 Azure AD 上创建适当的应用注册,并为 Blazor 应用配置开箱即用的验证所需的配置和代码。我们可以通过检查 appsettings.json 来确认。
并且,如果你到 Azure 门户的 Azure AD 注册页签中查看,还可以看到与 Visual Studio 中看到的信息想匹配的应用注册资料。
不需要写一行代码,我们的 Blazor 应用在用户访问任何页面之前,就可以提示用户。我们可以通过运行应用来快速测试该应用。在我们第一次访问该站点的时候,我们将被提示这些应用要求的 (默认) 权限,这里是读取用户的资料。
!
到了这一步,你可能认为我们的任务已经完成了,实际上,还有许多事情要做。首先,默认的模版使用了老式的,默认 v1 版本的 Azure AD 端点。如果你想知道为什么你应当使用 Microsoft identity platform 并使用 v2 版本的端点,你可以查看 Microsoft identity platform 文档。
使用 Microsoft.Identity.Web 现代化验证
在 Build 2020 中,我们为 ASP.NET Core 3.1 (及后继版本) 宣布了一个新的验证和令牌管理库。新的库对复杂性进行了很棒的大量抽象,支持开发者只需要很少的代码就可以实现验证。而且,新库最大的优势是因为该库构建与 MSAL 之上,你不再需要使用两个单独的库来先进行验证,然后获得一个令牌来访问后端的 API。所以,让我们看一下如何迁移到这个最新的库上。
注意:Microsoft.Identity.Web 仍然在预览状态,它将很快发布
注意:现在 1.0 已经发布。发布时间:2020/10/1
注意:现在 1.1.0 已经发布,发布时间:Tuesday, October 6, 2020 (10/6/2020)
首先,我们需要下载这个新的 NuGet 包
- Microsoft.Identity.Web - 1.1.0 已经发布
- Microsoft.Identity.Web.UI - 1.1.0 已经发布
然后,我们需要修改几行代码来清除老的验证代码并切换到新的代码。
打开 Startup() 并替换代码,下面是原来的代码:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
替换为:
services.AddMicrosoftWebAppAuthentication(Configuration);
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddMicrosoftIdentityUI();
使用 1.1 SDK 后,应该为:
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddMicrosoftIdentityUI();
最后,我们需要确保我们的应用可以使用正确的 v2 版本端点来进行登录和登出。打开 LoginDisplay.razor 并进行如下的更新:
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<a href="MicrosoftIdentity/Account/SignOut">Log out</a>
</Authorized>
<NotAuthorized>
<a href="MicrosoftIdentity/Account/SignIn">Log in</a>
</NotAuthorized>
</AuthorizeView>
你需要注意到,这里并没有特定的用来登录和登出的页面。相反,它们构建在 Microosft.Identity.Web.dll 内部。所以,在我们更新区域到 "MicrosoftIdentity" 的时候,不再需要其它的修改了。
当我们再次从 Visual Stuido 运行应用的时候,我们从 v2 中获得新的登录体验,例如无口令和多因子验证。最棒的是这些功能被设计为不需要修改任何代码,随着 Azure AD 的管理被配置为使用这些设置,所有的用户可以从更强的安全性中获益。
如你所见,使用很少的代码,我们可以借助于 Microsoft.Identity.Web 库基于 Azure AD 来验证用户。
从 Microsoft Graph 提取数据
Microsoft Graph 提供了大量的 API 来支持你基于用户自己的数据构建丰富的沉浸式的应用。在下面的步骤中,我们将拉取用户的电子邮件并将它们显示在应用内。为达到该目标,我们首先需要在 Azure AD 上扩展应用注册的权限,增加访问电子邮件数据的访问,然后我们需要在 Blazore 应用中添加一些代码来提取,并在其中的一个页面上显示数据。
Azure AD 门户
找到应用的注册,并进入 API 权限,选择添加新的权限,然后选择 Graph API,在这里,我们希望选择被代理权限,并选择 "Mail Read" 权限。
我们还需要创建一个用户密钥,因为我们的应用将需要一个验证令牌,和提取数据而不需要任何用户交互的方式。在同一个应用注册中,打开 Certificates 和 Secrets 页签,然后创建新的永不过期的密钥,如下所示:
确保你复制了密码,因为一旦你从该页面切换出去,你就再也不能访问它了。但是,如果需要的话,你总是可以重新创建它 - 这很简单且免费。
回到 Blazor 应用中,在 Visual Studio 中,我们首先需要在 appsettings.json 中添加客户密钥。在 AzureAD
的配置节,我们必须添加如下的行:
“ClientSecret”: “<your secret>”
在 Startup.cs 文件中,我们需要更新代码以确保使用正确的权限获取了适当的访问令牌,并将它保存在缓存中,以便我们在后继的应用中使用它访问 Microsoft Graph。我们将添加 HttpClient 到我们的服务管线中,来支持我们随后有效的发出 HTTP 调用到 Microsoft.Graph。
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi( new string[] { "User.Read", "Mail.Read" })
.AddInMemoryTokenCaches();
services.AddHttpClient();
然后,我们需要更新在 FetchData.razor 页面中的代码来获取我们的电子邮件数据,来替代默认的天气数据。下面的代码包含了所有我们需要获取电子邮件并显示在页面上的代码。
@page "/fetchdata"
@inject IHttpClientFactory HttpClientFactory
@inject Microsoft.Identity.Web.ITokenAcquisition TokenAcquisitionService
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (messages == null)
{
<p><em>Loading...</em></p>
}
else
{
<h1>Hello @userDisplayName !!!!</h1>
<table class="table">
<thead>
<tr>
<th>Subject</th>
<th>Sender</th>
<th>Received Time</th>
</tr>
</thead>
<tbody>
@foreach (var mail in messages)
{
<tr>
<td>@mail.Subject</td>
<td>@mail.Sender</td>
<td>@mail.ReceivedTime</td>
</tr>
}
</tbody>
</table>
}
@code {
private string userDisplayName;
private List<MailMessage> messages = new List<MailMessage>();
private HttpClient _httpClient;
protected override async Task OnInitializedAsync()
{
_httpClient = HttpClientFactory.CreateClient();
// get a token
var token = await TokenAcquisitionService.GetAccessTokenForUserAsync(new string[] { "User.Read", "Mail.Read" });
// make API call
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var dataRequest = await _httpClient.GetAsync("https://graph.microsoft.com/beta/me");
if (dataRequest.IsSuccessStatusCode)
{
var userData = System.Text.Json.JsonDocument.Parse(await dataRequest.Content.ReadAsStreamAsync());
userDisplayName = userData.RootElement.GetProperty("displayName").GetString();
}
var mailRequest = await _httpClient.GetAsync("https://graph.microsoft.com/beta/me/messages?$select=subject,receivedDateTime,sender&$top=10");
if (mailRequest.IsSuccessStatusCode)
{
var mailData = System.Text.Json.JsonDocument.Parse(await mailRequest.Content.ReadAsStreamAsync());
var messagesArray = mailData.RootElement.GetProperty("value").EnumerateArray();
foreach (var m in messagesArray)
{
var message = new MailMessage();
message.Subject = m.GetProperty("subject").GetString();
message.Sender = m.GetProperty("sender").GetProperty("emailAddress").GetProperty("address").GetString();
message.ReceivedTime = m.GetProperty("receivedDateTime").GetDateTime();
messages.Add(message);
}
}
}
public class MailMessage
{
public string Subject;
public string Sender;
public DateTime ReceivedTime;
}
}
重新运行应用,并确保先登出当前的用户,因为当前的令牌没有包含正确的访问权限,并且我们已经修改了一些代码。你将会注意到再次登录的时候,我们的提示增加了新的访问权限,这意味着一切如我们所愿。现在,除了基本的用户资料数据,应该还可以请求访问我们的电子邮件数据。
在授权之后,我们被导航到了 "Fetch Data" 页面,可以看到一些电子邮件!
如果你正确的如上演练,你现在应该可以看到类似上面图示中的你的电子邮件数据了。
总结
新的 Microsoft.Identity.Web 在简化验证和令牌管理方面做了出色的改进,你现在就应该开始使用它,在开始之前,有些事情值得你关注:
- 与普通的支持动态/增加提醒的 Web 应用不同,在 Blazor 中,你需要在一开始为你的应用请求所有需要的权限。失败的话,将会导致 TokenAcruisition 方法不能根据新的权限验证用户。这是 Blazor 机制的一部分,所以在创建应用的时候要记住这一点。
- 不是自己处理 Microsoft Graph HTTP 请求,你应该借助于 Microsoft Graph SDK,它简化了与 Microsoft Graph 的交互并提供了所有你需要序列化和反序列的对象。但是,在本示例中,我们仅仅遵循了建议 1,因为我们仅仅发出一个 Microsoft Graph 调用。
最后,你可以在 GitHub 上找到本示例 Blazor 应用程序的可运行示例的所有的源代码,
参考
如何使用 Azure Active Directory 认证和 Microsoft Graph 构建 Blazor Web 应用的更多相关文章
- 如何通过 PHP 获取 Azure Active Directory 令牌
在调用 Azure Rest API 时,如果是属于 Azure Resource Manager 的 API,则需要使用 Azure Active Directory (Azure AD)认证获取令 ...
- Azure Active Directory中的特权身份管理如何运作?
[TechTarget中国原创] 用户权限不是平等的.有些用户需要有大量权利和特权——通常这些都是管理员.企业在允许特权用户进行管理以及支持活动时,还需要意识到特权用户也有可能犯错.他们会犯错.他们可 ...
- SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理——深入的话需要去折腾Azure Active Directory
SRV记录 SRV记录 什么情况下会用到SRV记录? [SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理] SRV记录的添加方式 A.主机记录处格式为:服务的名字.协议的类型 例如 ...
- Azure AD(五)使用多租户应用程序模式让任何 Azure Active Directory 用户登录
一,引言 距离上次分享关于 “Azure AD" 的知识过去差不多2个多月了, 今天最近刚好也是学习,分享一下关于Azure AD 使用多租户应用程序模式让任何 Azure Active D ...
- 【Azure Developer】使用 adal4j(Azure Active Directory authentication library for Java)如何来获取Token呢
问题描述 使用中国区的Azure,在获取Token时候,参考了 adal4j的代码,在官方文档中,发现了如下的片段代码: ExecutorService service = Executors.new ...
- 简化 Web 应用程序与 Windows Azure Active Directory、ASP.NET 和 Visual Studio 的集成
大家好! 今天的博文深入讨论我们今天推出的开发人员工具和框架中的一些新功能.我们通过与 ASP.NET 和 Visual Studio 团队合作开发了一些重大的增强功能,让开发人员能够轻松使用 Win ...
- 移动服务和 Azure Active Directory 中基于角色的访问控制
编辑人员注释:本文章由 Matthew Henderson撰写 去年 11月,我们发布了 Azure Active Directory (AAD) 预览版作为移动服务身份提供程序.此举旨在为企业开 ...
- Azure Active Directory document ---reading notes
微软利用本地活动目录 Windows Server Active Directory 进行身份认证管理方面具有丰富的经验,现在这一优势已延伸基于云平台的Azure Active Directory.可 ...
- 使用 Azure Active Directory 管理 Azure 中的 HPC Pack 群集
Microsoft HPC Pack 2016 支持在 Azure 中部署 HPC Pack 群集的管理员将其与 Azure Active Directory (Azure AD) 集成. 请按照本文 ...
随机推荐
- Redis基础认识及常用命令使用
Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset(有序集 ...
- Java编程风格
来自<The Elements of Java Style>-<Java编程风格>一书,值得一读的书籍,会让你在细节上节省很多时间,合作之间更加愉快! 好处不多说了,但是有几个 ...
- 可以定时的FTP FTP如何实现每天定时上传文件
FTP上传一般都是一次性上传,我们在工作中总有一些文件,需要每天上传一次.有这么一款ftp上传工具是具有定时功能的.每天自动定时上传省时省力还操作简单. 工具名称:服务器管理工具(下载地址:http: ...
- 快速上手spring
一.初始程序 1.在父类pom导入所需要的jar包 2.编写一个实体类 3.创建一个beans.xml,创建一个bean即创建一个user对象,可在bean内配置property即设置属性值 4.用测 ...
- ASP.NET Web API 2系列(四):基于JWT的token身份认证方案
1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...
- 趣图:我说自己菜 vs 大佬说自己菜
扩展阅读 一大波趣图:CSS的力量 趣图:嫁人就嫁程序员,大妈都懂的! 趣图:向客户介绍的产品VS实际开发的产品 如何准备校招技术面试+一只小菜鸟的面试之路 向Spring大佬低头--大量源码流出 ...
- msf学习笔记
metasploit frame 这是一个渗透测试框架,围绕这个框架,我们就可以完成最终的目标,即渗透测试. 渗透测试者困扰:需要掌握数百个工具,上千条命令参数,很难记住. 新出现的漏洞PoC/EXP ...
- 俯瞰 Java 服务端开发
原文首发于 github ,欢迎 star . Java 服务端开发是一个非常宽广的领域,要概括其全貌,即使是几本书也讲不完,该文将会提到许多的技术及工具,但不会深入去讲解,旨在以一个俯瞰的视角去探寻 ...
- Git入门教程,详解Git文件的四大状态
大家好,欢迎来到周一git专题. git clone 在上一篇文章当中我们聊了怎么在github当中创建一个属于自己的项目(repository),简称repo.除了建立自己的repo之外,我们更多的 ...
- Power Designer建模之餐饮在线点评系统——需求模型实例
总览 一级需求 二级需求 管理门户 会员门户 三级需求 系统管理 企业中心 会员中心 统计分析 四级需求