基于角色的认证与Azure Active Directory集成

在企业级应用程序中,基于角色的认证(Role-Based Access Control, RBAC)是一种常见的安全机制。它允许系统管理员根据用户的角色分配不同的访问权限。例如,信用控制用户可以看到信用历史,而订单处理用户只需要知道账户有信用并且可以下单。本文将介绍如何使用Azure Active Directory(AAD)来实现基于角色的认证,并将其集成到ASP.NET应用程序中。

实现方法

ASP.NET中,实现基于角色的认证通常有以下几种方法:

  • 调用IPrincipal.IsInRole(role)方法。
  • 在类或方法上放置[PrincipalPermission(user, role)]属性。
  • 创建PrincipalPermission(user, role)实例并调用Demand()方法。

这些方法通常与来自活动目录或数据库的组一起使用,通过ASP.NET角色提供程序来实现。更多信息可以查看。

使用Azure Active Directory

如果想要使用Azure Active Directory并使用活动目录组来启用基于角色的认证,这不是原生支持的,需要查询"Azure Active Directory Graph API"。有关Azure Active Directory及其优势的更多信息,可以查看。

NuGet包Azure.ActiveDirectory的使用

接下来,将讨论如何使用NuGet包Azure.ActiveDirectory来轻松地为应用程序添加角色认证。

默认情况下,Visual Studio项目向导会设置项目使用Entity Framework作为ValidatingIssuerNameRegistry。由于在Azure中SQL存储成本较高,将切换到价格低廉的表存储。随着时间的推移,希望能够改进NuGet体验,减少手动步骤。本文的其余部分假设有一个Azure帐户和一个活动目录,或者可以从管理门户轻松创建一个新的。

在管理门户中,创建了2个用户和2个组在目录codeproject.onmicrosoft.com中:

  • admin@codeproject.onmicrosoft.com作为"Admin"组的成员,并具有"Global Administrator Role",这将允许在运行Visual Studio向导时在活动目录中创建应用程序。
  • member@codeproject.onmicrosoft.com作为"Member"组的成员。

将使用这些用户来测试角色认证是否在MVC示例应用程序中工作。

创建一个新的ASP.NET项目,选择MVC项目模板,并选择"更改认证"按钮,配置MVC项目使用活动目录。由于希望启用Azure图API返回组,需要确保选择了允许读取目录数据的选项。

已经输入了活动目录名称codeproject.onmicrosoft.com,并选择了"Single Sign On, Read directory data"以允许访问图。

App ID URI用于在Azure目录中标识应用程序,默认情况下这是从域名和项目名称自动生成的。

当点击OK时,使用管理员用户登录。

一旦Visual Studio创建了项目,需要在包管理器控制台中运行以下命令:

  • Install-Package Azure.ActiveDirectory
  • Install-Package Microsoft.WindowsAzure.ConfigurationManager(出于某种原因,NuGet依赖项没有被添加)
  • Update-Package(可选更新到最新版本)

现在需要对web.config进行一些修改,以注册存储帐户和AzureTableIssuerNameRegistry

AzureTableIssuerNameRegistry实现了ValidatingIssuerNameRegistry在Azure表存储上,而不是默认注册的实体框架提供程序。

默认情况下,配置将指向应用程序中由向导创建的DatabaseIssuerNameRegistry

更新issuerNameRegistry指向包注册表:

<issuerNameRegistry type="Azure.ActiveDirectory.AzureTableIssuerNameRegistry, Azure.ActiveDirectory" />

为了使AzureTableIssuerNameRegistry工作,需要设置appSettings或CloudSettings配置键Identity.StorageConnectionString为存储连接字符串,应该类似于:

<add key="Identity.StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=[name];AccountKey=[key]" />

正确的连接字符串可以在Azure管理门户中轻松找到,或者在Visual Studio的服务器资源管理器属性面板中。

在App_Start文件夹下创建的IdentityConfig需要更新,以从Azure刷新其密钥,而不是默认的EF注册表。更新方法RefreshValidationSettings()

public static void RefreshValidationSettings() { string metadataLocation = ConfigurationManager.AppSettings["ida:FederationMetadataLocation"]; Azure.ActiveDirectory.AzureTableIssuerNameRegistry.RefreshKeys(metadataLocation); }

ConfigureIdentity()方法中,需要告诉身份配置从Azure图中获取角色声明。通过添加以下行来实现这一点:

FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager = new Azure.ActiveDirectory.GraphClaimsAuthenticationManager();

现在可以按F5运行应用程序,当提示登录时,应该能够登录并呈现默认站点。

默认情况下,HomeController声明了一堆变量,并请求图API返回Json,该Json被填充到之前删除的UserProfile类中,包含在HomeViewModel.cs中。将更新HomeController以使用IActiveDirectoryGraphClient并将当前用户传递给UserProfile视图。

using System.Web.Mvc; using Azure.ActiveDirectory; namespace RolesBasedAuthenticationSample.Controllers { public class HomeController : Controller { private readonly IActiveDirectoryGraphClient _graphClient = new GraphClient(); [Authorize] public ActionResult UserProfile() { return View(_graphClient.CurrentUser); } public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

由于不再使用ASP.NET项目中创建的UserProfile,需要快速更新视图以使用对象。

@model Azure.ActiveDirectory.AzureGraphService.Microsoft.WindowsAzure.ActiveDirectory.User @{ ViewBag.Title = "User Profile"; } <h2> @ViewBag.Title. </h2> <table class="table table-bordered table-striped"> <tr> <td> Display Name </td> <td> @Html.DisplayFor(m=>m.displayName) </td> </tr> <tr> <td> First Name </td> <td> @Html.DisplayFor(m=>m.givenName) </td> </tr> <tr> <td> Last Name </td> <td> @Html.DisplayFor(m=>m.surname) </td> </tr> </table>

为了演示角色,将为之前创建的每个组添加一个管理员页面和一个成员页面。

添加2个新视图的动作:

[PrincipalPermission(SecurityAction.Demand, Role="Admin")] public ActionResult Admin() { ViewBag.Message = "Your admin page."; return View(); } [PrincipalPermission(SecurityAction.Demand, Role="Member")] public ActionResult Member() { ViewBag.Message = "Your member page."; return View(); }

在共享布局文件中为新页面添加2个菜单链接,找到顶部菜单操作链接的navbar,并更改

    列表:

<ul class="nav navbar-nav"> <li> @Html.ActionLink("Home", "Index", "Home") </li> <li> @Html.ActionLink("About", "About", "Home") </li> <li> @Html.ActionLink("Contact", "Contact", "Home") </li> @if (User.IsInRole("Member")) { <li> @Html.ActionLink("Member", "Member", "Home") </li> } @if (User.IsInRole("Admin")) { <li> @Html.ActionLink("Admin", "Admin", "Home") </li> } </ul> @{ ViewBag.Title = "Admin"; } <h2>@ViewBag.Title. </h2> <h3>@ViewBag.Message </h3> <p>Welcome to your admin page. </p> @{ ViewBag.Title = "Member"; } <h2>@ViewBag.Title. </h2> <h3>@ViewBag.Message </h3> <p>Welcome to your member page. </p>
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485