在 .NET Core 中实现基于策略和基于角色的授权

本文主要介绍如何使用 .NET Core 实现基于策略的授权。 如果您需要了解授权技术的基础知识,请参阅链接。让我们来分解一下关键组件:

1、身份验证设置

• 首先,在您的应用程序中设置身份验证。这可确保正确识别和验证用户身份。

• 您通常会使用第三方身份验证提供程序(如 Microsoft Identity Platform)来处理用户登录和颁发令牌。

2、授权策略

• 接下来,定义授权策略。这些策略决定谁可以访问应用程序的特定部分。

• 策略可以很简单(例如"仅限经过身份验证的用户"),也可以更复杂(基于声明、角色或自定义要求)。

3、默认策略

• 创建一个适用于所有端点的默认策略,除非被覆盖。

• 例如,您可能要求用户经过身份验证并具有特定声明(如首选用户名)。

4、自定义策略

• 为特定场景添加自定义策略。这些策略允许对访问进行细粒度的控制。

• 例如,您可以根据权限创建策略(例如"创建/编辑用户"或"查看用户")。

5、权限要求

• 定义权限要求(例如 PermissionAuthorizationRequirement)。这些代表特定的操作或功能。

• 对于每个要求,检查用户是否具有必要的权限(基于其角色或其他标准)。

6、基于角色的授权

• 可选地,合并基于角色的授权。

• 角色将具有相似访问级别的用户分组(例如,"管理员"、"用户"等)。您可以将角色分配给用户。

7、授权处理程序

• 实施自定义授权处理程序(例如 AuthorizationHandler)。

• 这些处理程序评估用户是否满足要求(例如,具有正确的权限或角色)。

8、控制器动作

• 在控制器操作中,应用授权规则。

• 使用 [Authorize] 具有策略或角色的属性。

9、中间件结果处理

• 自定义如何处理授权结果(例如,401 未授权或 403 禁止响应)。

• 您可以创建一个 AuthorizationMiddlewareResultHandler 来管理此行为

让我们继续进行 Web API 的实际编码:

Program.cs: 按原样使用 Azure AD 身份验证。确定授权的权限密钥。

AddPolicy 方法中只有一个策略

//In Program.cs file, add the below code

var builder = WebApplication.CreateBuilder(args);

// Authentication using Microsoft Identity Platform

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

// Default policy-based authorization

services.AddAuthorizationCore(options =>

{

options.DefaultPolicy = new AuthorizationPolicyBuilder()

.RequireAuthenticatedUser()

.RequireClaim("preferred_username")

.RequireScope("user_impersonation")

.Build();

options.AddPolicy("Permission1", policy =>

policy.Requirements.Add(new PermissionAuthorizationRequirement("Permission1")));

options.AddPolicy("Permission2", policy =>

policy.Requirements.Add(new PermissionAuthorizationRequirement("Permission2")));

});

// Authorization handler

services.AddScoped<IAuthorizationHandler, AuthorizationHandler>();

// Middleware result handler for response errors (401 or 403)

services.AddScoped<IAuthorizationMiddlewareResultHandler, AuthorizationMiddlewareResultHandler>();

// Other services and configurations...

PermissionAuthorizationRequirement .cs: 只需复制并粘贴要求

//Create new PermissionAuthorizationRequirement.cs file for Custom requirement for permission-based authorization

public class PermissionAuthorizationRequirement : IAuthorizationRequirement

{

public PermissionAuthorizationRequirement(string allowedPermission)

{

AllowedPermission = allowedPermission;

}

public string AllowedPermission { get; }

}

AuthorizationHandler.cs:( 只需复制并粘贴代码。确保使用应用程序管理器点击 DB 调用以获取权限列表)

// Custom authorization handler to check user permissions

public class AuthorizationHandler : AuthorizationHandler<PermissionAuthorizationRequirement>

{

// Business layer service for user-related operations

private readonly IAppManager _appManager;

public AuthorizationHandler(IAppManager appManager)

{

_appManager= appManager;

}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement)

{

// Find the preferred_username claim

var preferredUsernameClaim = context.User.Claims.FirstOrDefault(c => c.Type == "preferred_username");

if (preferredUsernameClaim is null)

{

// User is not authenticated

context.Fail(new AuthorizationFailureReason(this, "UnAuthenticated"));

return;

}

// Call the business layer method to check if the user exists

var user = await _appManager.GetUserRolesAndPermissions(preferredUsernameClaim);

if (user is null || !user.IsActive)

{

// User does not exist or is inactive

context.Fail(new AuthorizationFailureReason(this, "UnAuthenticated"));

return;

}

// Select the list of permissions that the user is assigned

// Here you will fetch the Permission1 and Permission2

var userPermissions = user.UserPermissions?.Select(k => k.PermissionKey);

// Get the current permission key from the controller's action method

string allowedPermission = requirement.AllowedPermission;

// Check if the current request carries this permission

if (userPermissions.Any(permission => permission == allowedPermission))

{

// Permission granted

context.Succeed(requirement);

return;

}

// Permission denied

context.Fail();

}

}

AuthorizationMiddlewareResultHandler.cs: 只需复制粘贴即可。无需任何更改。

// AuthorizationMiddlewareResultHandler to decide response code (401 or success)

public class AuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler

{

private readonly ILogger<AuthorizationMiddlewareResultHandler> _logger;

private readonly Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler _defaultHandler = new();

public AuthorizationMiddlewareResultHandler(ILogger<AuthorizationMiddlewareResultHandler> logger)

{

_logger = logger;

}

public async Task HandleAsync(

RequestDelegate next,

HttpContext context,

AuthorizationPolicy policy,

PolicyAuthorizationResult authorizeResult)

{

var authorizationFailureReason = authorizeResult.AuthorizationFailure?.FailureReasons.FirstOrDefault();

var message = authorizationFailureReason?.Message;

if (string.Equals(message, "UnAuthenticated", StringComparison.CurrentCultureIgnoreCase))

{

// Set response status code to 401 (Unauthorized)

context.Response.StatusCode = "401";

_logger.LogInformation("401 failed authentication");

return;

}

// If not unauthorized, continue with default handler

await _defaultHandler.HandleAsync(next, context, policy, authorizeResult);

}

}

Controller.cs: 最后,在仪表板控制器中添加 [Authorize] 和 [Policies] 属性。这里定义Permission1和Permission2。

// Dashboard controller

Authorize

Route("api/\[controller\]")

ApiController

public class DashboardController : ControllerBase

{

HttpGet

Route("get-dashboardDetails")

Authorize(Policy = "Permission1")

public async Task GetAllDashboardDetailsAsync()

{

// Your logic for fetching all user details

return await GetAllDashboardDetailsAsync();

}

HttpGet

Route("create-product")

Authorize(Policy = "Permission2")

//[Authorize(Policy = nameof(Read string from ENUM))]

public async Task CreateProductAsync([FromBody] Product product)

{

// Your logic for creating a new product

}

}

现在,如果您想在 Web API 代码中结合使用基于角色的授权,请按照以下步骤操作,或者您也可以跳过此步骤。它与我们基于策略的授权的步骤几乎相同,只有一些细微的差别,您可以在代码中发现。

一. 注册 RoleAuthorizationHandler

在您的 Program.cs 文件中,只需添加以下行即可注册 RoleAuthorizationHandler

builder.Services.AddScoped<IAuthorizationHandler, RoleAuthorizationHandler>();

二. RoleAuthorizationHandler

下面是 RoleAuthorizationHandler.cs 检查用户是否具有所需角色的处理器。再创建一个处理器

public class RoleAuthorizationHandler : AuthorizationHandler<RolesAuthorizationRequirement>

{

private readonly IAppManager _appManager;

public RoleAuthorizationHandler(IAppManager appManager)

{

_appManager= appManager;

}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)

{

// Find the preferred_username claim

Claim claim = context.User.Claims.FirstOrDefault(c => c.Type == "preferred_username");

if (claim is not null)

{

// Get user details

var userRoles = await _appManager.GetUserRolesAndPermissions(claim.Value);

// Check if the user's roles match the allowed roles

var roles = requirement.AllowedRoles;

if (userRoles .Any(x => roles.Contains(x)))

{

context.Succeed(requirement); // User has the required roles

}

else

{

context.Fail(); // User does not have the required roles

return;

}

}

await Task.CompletedTask;

}

}

三. 在 DashboardController 中的使用

在你的 DashboardController 中DashboardController,你可以同时使用角色和策略进行授权。例如:

HttpGet

Route("get-dashboardDetails")

Authorize(Roles = "Super_Admin, Role_Administrator")\] // Can have multiple roles. You can choose either Roles or Policy or both \[Authorize(Policy = "Permission1")\] // Can have only one policy per action to accept. public async Task GetAllDashboardDetailsAsync() { // Your logic for fetching all user details return await GetAllDashboardDetailsAsync(); } 就这样。你的 Web API 将会像魔法一样运行。:-)。 **如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。**

相关推荐
MoFe12 天前
【.net core】【NPOI】读取表格信息(处理合并行表格数据)
.netcore
The Sheep 20232 天前
.NetCore MVC
mvc·.netcore
一包烟电脑面前做一天2 天前
.NetCore下Ocelot + Nacos 实现负载均衡
nacos·负载均衡·.netcore·ocelot·ocelot集成nacos
一个帅气昵称啊2 天前
NetCoreKevin-DDD-微服务-WebApi-AI智能体、AISK集成、MCP协议服务、SignalR、Quartz 框架-16-部署与基础设施
微服务·云原生·架构·系统架构·.netcore
忧郁的蛋~3 天前
在.NET标准库中进行数据验证的方法
后端·c#·asp.net·.net·.netcore
willhuo3 天前
学生请假就餐系统
运维·服务器·.netcore
一包烟电脑面前做一天4 天前
.NetCore 接入 Nacos,实现配置中心和服务注册
nacos·.netcore·服务注册发现·配置中心
切糕师学AI7 天前
.Net Core Web 架构(管道机制)的底层实现
中间件·系统架构·kestrel·mvc·.netcore·路由·请求管道
时光追逐者10 天前
C#/.NET/.NET Core技术前沿周刊 | 第 51 期(2025年8.18-8.24)
c#·.net·.netcore·.net core