声明式策略基础One—(菜鸡随笔)

声明式策略基础One—(菜鸡随笔)

在Web应用程序中,安全性是至关重要的。为了保护敏感数据和操作,您需要对用户进行身份验证和授权。ASP.NET Core提供了一种称为声明式策略的功能来管理Web应用程序中的授权。

声明式策略是一个基于角色和声明的授权机制,它允许开发人员在应用程序中定义自定义的授权规则,并使用这些规则来限制特定用户对资源的访问。与基于角色的授权相比,声明式策略更加灵活和精细,可以根据实际业务需要进行配置和调整。

本文将介绍如何在ASP.NET Core应用程序中使用声明式策略,以及最佳实践和注意事项。

基础

在开始之前,我们需要了解一些授权和认证的基础知识。

授权和认证的区别和联系:

  • 认证是验证用户身份的过程,通常涉及用户名和密码等凭据;
  • 授权是决定用户是否有权访问特定资源或执行特定操作的过程。

策略授权与角色授权的区别:

  • 角色授权是一种基于角色的授权机制,其中用户被授予某个角色,并且该角色具有特定的权限;
  • 策略授权是一种基于声明的授权机制,其中用户被授予一组声明或属性(如用户名、电子邮件地址等),并且这些声明或属性用于限制特定用户对资源的访问。

声明式策略的基本组成部分:

  • 授权要求(Authorization Requirement):定义一个规则,描述某种授权策略,例如:用户必须拥有特定的声明才能访问一个资源。
  • 授权处理程序(Authorization Handler):验证授权要求,决定是否授予用户访问资源的权限。
  • 授权策略(Authorization Policy):将授权要求和处理程序绑定在一起,以便在授权过程中使用。

策略的应用方式:

  • 声明式策略可以应用于API端点和控制器上,限制用户访问这些资源;
  • 声明式策略也可以用于资源授权,限制用户访问敏感数据、文件等资源。

实现

定义自定义策略和验证规则

要定义自定义的授权策略和验证规则,请遵循以下步骤:

  1. 创建一个名为RecordPolicy的授权策略,并指定要求和处理程序。在此示例中,我们使用RecordAccessRequirement和RecordAccessRequirementHandler。
services.AddAuthorization(options => {
    options.AddPolicy("RecordPolicy", policy =>
        policy.Requirements.Add(new RecordAccessRequirement())
    );
});
  1. 在API端点或控制器上使用[Authorize]特性,并指定要使用的策略。这可以通过指定Policy属性和Resource属性来完成。Resource属性可将当前请求的资源ID传递给授权处理程序。
[HttpGet("{id}")]
[Authorize(Policy = "RecordPolicy", Resource = "{id}")]
public ActionResult<Record> GetRecord(int id)
{
    // 处理Get请求
}

在上面的代码中,我们使用[Authorize]特性来限制用户访问GET操作。只有拥有名为"RecordPolicy"的策略并具有指定资源ID的用户才能访问该API。

嵌套策略的使用

嵌套策略是指将多个策略组合在一起使用的情况。例如,您可能会创建一个名为"AdminPolicy"的策略,该策略要求用户具有名为"Admin"的角色或拥有特定的声明。在ASP.NET Core中,您可以通过以下方式实现嵌套策略:

services.AddAuthorization(options => {
    options.AddPolicy("AdminPolicy", policy => {
        policy.RequireRole("Admin");
        policy.RequireClaim("IsAdmin", "true");
    });
 
    options.AddPolicy("RecordPolicy", policy =>
        policy.Requirements.Add(new RecordAccessRequirement())
    );
 
    options.AddPolicy("CompositePolicy", policy =>
        policy.RequireAssertion(context =>
            context.User.HasClaim(c => c.Type == "Database" && c.Properties.ContainsKey("Write") && bool.Parse(c.Properties["Write"]))) &&
            context.User.HasPolicy("AdminPolicy") &&
            context.User.HasPolicy("RecordPolicy")
        )
    );
});

在上面的代码中,我们创建了一个名为"AdminPolicy"的策略,要求用户具有"Admin"角色或具有名为"IsAdmin"声明且值为"true"。然后,我们创建了两个其他的策略:"RecordPolicy"和"CompositePolicy"。

"RecordPolicy"策略使用了前面定义的RecordAccessRequirement授权要求。

"CompositePolicy"策略是一个嵌套策略,它组合了三个不同的策略。它要求用户具有一些特定的声明、"AdminPolicy"策略和"RecordPolicy"策略。这意味着只有拥有这三个策略的用户才能访问API端点或控制器。

策略缓存的配置

在大多数情况下,应将策略缓存在内存中,以提高性能。

ASP.NET Core提供了两种缓存策略:MemoryCache和DistributedCache。MemoryCache存储在应用程序的进程内,而DistributedCache存储在应用程序的进程之间共享的位置。

以下是如何使用MemoryCache配置策略缓存:

services.AddAuthorization(options => {
    options.CacheAuthorizeData = true;
 
    options.AddPolicy("RecordPolicy", policy =>
        policy.Requirements.Add(new RecordAccessRequirement())
    );
});

在上面的代码中,我们启用了缓存策略,并添加了名为"RecordPolicy"的授权策略。

资源授权

除了限制用户访问API端点和控制器外,还可以使用声明式策略限制用户访问资源,例如数据库、文件等。资源授权是一种基于资源的授权验证,它允许您根据资源ID和访问类型(例如读取或写入)来限制用户对特定资源的访问。

要实现资源授权,请遵循以下步骤:

在授权要求中添加一个资源属性。

public class ResourceAccessRequirement : IAuthorizationRequirement {
    public string Resource { get; set; }
}

创建一个自定义的授权处理程序,用于验证用户是否具有特定的声明且该声明与请求的资源匹配。

public class ResourceAccessHandler : AuthorizationHandler<ResourceAccessRequirement> {
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ResourceAccessRequirement requirement) {
        if (context.User.HasClaim(c => c.Type == "Resource" && c.Value == requirement.Resource && c.Properties.ContainsKey(requirement.AccessType) && bool.Parse(c.Properties[requirement.AccessType]))) {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

在上面的代码中,我们检查当前请求的用户是否具有名为"Resource"、值等于要访问的资源ID的声明,并且该声明具有指定的访问类型("Read"或"Write")且属性值为true。如果条件成立,则调用context.Succeed方法以指示授权通过;否则返回Task.CompletedTask表示授权失败。

将ResourceAccessHandler添加到服务容器中。

services.AddSingleton<IAuthorizationHandler, ResourceAccessHandler>();

在授权策略中添加ResourceAccessRequirement要求,并指定要使用的处理程序。

services.AddAuthorization(options => {
    options.AddPolicy("ResourcePolicy", policy =>
        policy.Requirements.Add(new ResourceAccessRequirement { AccessType = "Read" })
            .Add(new ResourceAccessRequirement { AccessType = "Write" })
            .HandlerType = typeof(ResourceAccessHandler)
    );
});

在上面的代码中,我们创建了一个名为"ResourcePolicy"的授权策略,并将两个ResourceAccessRequirement授权要求添加到该策略中。我们还指定了要使用的ResourceAccessHandler处理程序。

在API端点或控制器上使用[Authorize]特性,并指定要使用的策略和资源ID。

[HttpGet("{id}")]
[Authorize(Policy = "ResourcePolicy", Resource = "{id}")]
public ActionResult<Resource> GetResource(int id) {
    // 处理Get请求
}

在上面的代码中,我们使用[Authorize]特性来限制用户访问GET操作。只有拥有名为"ResourcePolicy"的策略且具有指定的资源ID、读取或写入访问类型的用户才能访问该API。

示例

以下示例演示如何在ASP.NET Core应用程序中实现声明式策略。

在此示例中,我们将创建一个简单的Web API应用程序,它允许用户查看和更新他们的个人资料。我们将定义两个授权策略:"ViewProfile"和"UpdateProfile",并限制用户访问API端点。

创建授权要求和处理程序

首先,我们将创建两个授权要求:"ViewProfileRequirement"和"UpdateProfileRequirement",并定义它们的处理程序。

public class ViewProfileRequirement : IAuthorizationRequirement
{
}

public class UpdateProfileRequirement : IAuthorizationRequirement
{
}

public class ProfileAccessHandler : AuthorizationHandler<IAuthorizationRequirement, string>
{
    private readonly IUserService _userService;

    public ProfileAccessHandler(IUserService userService)
    {
        _userService = userService;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IAuthorizationRequirement requirement, string resource)
    {
        if (requirement is ViewProfileRequirement && context.User.Identity.Name == resource)
        {
            context.Succeed(requirement);
        }
        else if (requirement is UpdateProfileRequirement && context.User.Identity.Name == resource && context.User.HasClaim(c => c.Type == "IsAdmin" && bool.Parse(c.Value)))
        {
            context.Succeed(requirement);
        }
        else
        {
            // 如果没有授权成功,则检查是否存在相应的用户记录
            var user = await _userService.GetUserByNameAsync(resource);

            if (user != null)
            {
                context.Fail();
            }
        }
    }
}

在ProfileAccessHandler类中,我们继承了AuthorizationHandler<IAuthorizationRequirement, string>类,并实现了HandleRequirementAsync方法来处理授权需求。在这个方法中,我们首先检查传入的requirement对象是否为ViewProfileRequirement,并且当前用户的用户名是否等于resource(即要访问的用户的用户名)。如果满足这两个条件,则调用context.Succeed(requirement)方法表示授权成功。

然后,我们检查传入的requirement对象是否为UpdateProfileRequirement,并且当前用户的用户名是否等于resource,以及当前用户是否具备名为“IsAdmin”的声明,且该声明的值为true。如果满足这三个条件,则同样调用context.Succeed(requirement)方法表示授权成功。

最后,如果以上两种情况都不成立,则说明当前用户没有访问或更新指定用户的资料的权限。在这种情况下,我们调用_userService.GetUserByNameAsync(resource)方法来获取与指定用户名相对应的用户记录。如果存在这样的用户记录,则调用context.Fail()方法表示授权失败,否则什么也不做(即表示未找到此资源)。

需要注意的是,在这个示例中,我们使用了IUserService服务来查询数据库中的用户记录。在实际应用中,您可以使用自己的数据访问层、ORM框架或其他方式来实现相应的功能。

配置策略

然后,我们将配置授权策略,并将其添加到服务容器中。

services.AddAuthentication(...)
        .AddJwtBearer(...)

services.AddAuthorization(options =>
{
    options.AddPolicy("ViewProfilePolicy", policy => policy.Requirements.Add(new ViewProfileRequirement()));
    options.AddPolicy("UpdateProfilePolicy", policy => policy.Requirements.Add(new UpdateProfileRequirement()));
});

services.AddSingleton<IAuthorizationHandler, ProfileAccessHandler>();

并将两个自定义的身份验证需求添加到名为“ViewProfilePolicy”和“UpdateProfilePolicy”的授权策略中。然后,我们将ProfileAccessHandler类注册为实现IAuthorizationHandler接口的服务。

在需要进行身份验证和授权的控制器、操作方法或 Razor 页面中,添加相应的身份验证和授权特性,例如:

[Authorize(Policy = "ViewProfilePolicy")]
[HttpGet("{username}")]
public async Task<IActionResult> GetProfile(string username)
{
    // 处理获取用户资料的逻辑
}

[Authorize(Policy = "UpdateProfilePolicy")]
[HttpPut("{username}")]
public async Task<IActionResult> UpdateProfile(string username, [FromBody] UserProfileModel model)
{
    // 处理更新用户资料的逻辑
}

在这个示例中,我们使用了Authorize特性来声明需要进行身份验证和授权。在ViewProfilePolicy策略下,只有具备ViewProfileRequirement身份验证需求的用户才能访问获取用户资料的操作方法。在UpdateProfilePolicy策略下,只有具备UpdateProfileRequirement身份验证需求且具备“IsAdmin”声明的值为true的用户才能访问更新用户资料的操作方法。

在API端点中使用授权策略

最后,我们将在API端点中使用授权策略,以限制用户访问。我们还可以使用[Authorize]特性来限制用户访问整个控制器或API端点。

[HttpGet("{username}")]
[Authorize(Policy = "ViewProfile", Resource = "{username}")]
public ActionResult<UserProfile> GetProfile(string username) {
    // 处理GET请求
}
 
[HttpPut("{username}")]
[Authorize(Policy = "UpdateProfile", Resource = "{username}")]
public ActionResult<UserProfile> UpdateProfile(string username, [FromBody] UserProfile profile) {
    // 处理PUT请求
}

在上面的代码中,我们使用[Authorize]特性来限制GET和PUT操作。只有满足指定的授权策略且具有指定的资源ID的用户才能访问这些API。

总结

声明式策略是一种灵活、可维护和可测试的授权机制,它允许您定义自定义的授权规则,并使用这些规则来限制特定用户对资源的访问。在ASP.NET Core中,您可以使用授权要求、授权处理程序和授权策略来实现声明式策略。声明式策略可以应用于API端点和控制器上,也可以用于资源授权,以限制用户访问敏感数据、文件等资源。

在实践中,您应该遵循最佳实践,例如将授权要求和处理程序分离、配置策略缓存和使用嵌套策略等。通过实现这些实践,您可以创建更加灵活、清晰和安全的应用程序,保障用户数据的安全和隐私。

好的,以下是一个完整的示例,演示如何在ASP.NET Core中使用声明式策略来限制用户访问敏感资源。

1. 创建应用程序

首先,我们将创建一个新的ASP.NET Core应用程序,并添加所需的NuGet包。

dotnet new webapi -n SecureApi
cd SecureApi
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

2. 定义数据模型

我们将定义一个User数据模型,用于表示应用程序中的用户。

public class User {
    public int Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public bool IsAdmin { get; set; }
}

3. 添加身份验证

我们将使用JWT身份验证机制来保护API端点。我们将在Startup.cs文件中配置身份验证服务和中间件。

public void ConfigureServices(IServiceCollection services) {
    // 添加身份验证服务
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options => {
            options.TokenValidationParameters = new TokenValidationParameters {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Configuration["Jwt:Issuer"],
                ValidAudience = Configuration["Jwt:Issuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
            };
        });

    // 添加授权服务
    services.AddAuthorization();

    // 添加数据库上下文
    services.AddDbContext<AppDbContext>(options =>
        options.UseInMemoryDatabase(databaseName: "SecureApi")
    );

    // 添加控制器
    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    // 启用身份验证中间件
    app.UseAuthentication();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints => {
        endpoints.MapControllers();
    });
}

在上面的代码中,我们首先使用AddAuthentication方法配置JWT身份验证服务。然后,我们启用身份验证中间件,并使用UseAuthorization方法启用授权中间件。

4. 添加授权要求和处理程序

接下来,我们将定义两个授权要求:"ViewResourceRequirement"和"UpdateResourceRequirement",并添加处理程序"ResourceAccessHandler"。

public class ViewResourceRequirement : IAuthorizationRequirement {
    public string Resource { get; set; }
}

public class UpdateResourceRequirement : IAuthorizationRequirement {
    public string Resource { get; set; }
}

public class ResourceAccessHandler : AuthorizationHandler<IAuthorizationRequirement> {
    private readonly AppDbContext _dbContext;

    public ResourceAccessHandler(AppDbContext dbContext) {
        _dbContext = dbContext;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IAuthorizationRequirement requirement) {
        if (requirement is ViewResourceRequirement viewRequirement && context.User.Identity.Name == viewRequirement.Resource) {
            context.Succeed(requirement);
        } else if (requirement is UpdateResourceRequirement updateRequirement && context.User.Identity.Name == updateRequirement.Resource && context.User.HasClaim(c => c.Type == "IsAdmin" && bool.Parse(c.Value))) {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

在上面的代码中,我们为每个授权要求编写一个单独的处理程序。在HandleRequirementAsync方法中,我们检查当前请求的用户是否满足授权要求,并调用context.Succeed方法以指示授权通过。

5. 配置授权策略

接下来,我们将配置授权策略,并将其添加到服务容器中。

public void ConfigureServices(IServiceCollection services) {
    // 添加授权服务
    services.AddAuthorization(options => {
        options.AddPolicy("ViewResource", policy =>
            policy.Requirements.Add(new ViewResourceRequirement())
                .HandlerType = typeof(ResourceAccessHandler)
        );

        options.AddPolicy("UpdateResource", policy =>
            policy.Requirements.Add(new UpdateResourceRequirement())
                .HandlerType = typeof(ResourceAccessHandler)
        );
    });

    // 添加数据库上下文
    services.AddDbContext<AppDbContext>(options =>
        options.UseInMemoryDatabase(databaseName: "SecureApi")
    );

    // 添加控制器
    services.AddControllers();
}

在上面的代码中,我们将授权服务添加到ConfigureServices方法中,并在其中配置授权策略。我们创建了两个授权策略:"ViewResource"和"UpdateResource"。我们还指定了要使用的ResourceAccessHandler处理程序。

6. 添加API端点

最后,我们将添加两个API端点:GetResource和UpdateResource。

[HttpGet("{id}")]
[Authorize(Policy = "ViewResource", Resource = "{id}")]
public ActionResult<Resource> GetResource(int id) {
    var resource = _dbContext.Resources.FirstOrDefault(r => r.Id == id);

    if (resource == null) {
        return NotFound();
    }

    return Ok(resource);
}

[HttpPut("{id}")]
[Authorize(Policy = "UpdateResource", Resource = "{id}")]
public ActionResult<Resource> UpdateResource(int id, [FromBody] Resource resource) {
    var existingResource = _dbContext.Resources.FirstOrDefault(r => r.Id == id);

    if (existingResource == null) {
        return NotFound();
    }

    existingResource.Value = resource.Value;

    _dbContext.SaveChanges();

    return Ok(existingResource);
}

在上面的代码中,我们使用[Authorize]特性来限制GET和PUT操作。只有满足指定的授权策略且具有指定的资源ID的用户才能访问这些API。

完整示例代码

以下是完整的示例代码:

using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Microsoft.EntityFrameworkCore;
using System.IdentityModel.Tokens.Jwt;

namespace SecureApi
{
    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public bool IsAdmin { get; set; }
    }

    public class Resource
    {
        public int Id { get; set; }
        public string Value { get; set; }
    }

    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options)
            : base(options) { }

        public DbSet<User> Users { get; set; }
        public DbSet<Resource> Resources { get; set; }
    }

    public class ViewResourceRequirement : IAuthorizationRequirement
    {
        public string Resource { get; set; }
    }

    public class UpdateResourceRequirement : IAuthorizationRequirement
    {
        public string Resource { get; set; }
    }

    public class ResourceAccessHandler : AuthorizationHandler<IAuthorizationRequirement>
    {
        private readonly AppDbContext _dbContext;

        public ResourceAccessHandler(AppDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IAuthorizationRequirement requirement)
        {
            if (requirement is ViewResourceRequirement viewRequirement && context.User.Identity.Name == viewRequirement.Resource)
            {
                context.Succeed(requirement);
            }
            else if (requirement is UpdateResourceRequirement updateRequirement && context.User.Identity.Name == updateRequirement.Resource && context.User.HasClaim(c => c.Type == "IsAdmin" && bool.Parse(c.Value)))
            {
                context.Succeed(requirement);
            }

            return Task.CompletedTask;
        }
    }

    [Route("api/[controller]")]
    [ApiController]
    public class UsersController : ControllerBase
    {
        private readonly AppDbContext _dbContext;
        private readonly IConfiguration _configuration;

        public UsersController(AppDbContext dbContext, IConfiguration configuration)
        {
            _dbContext = dbContext;
            _configuration = configuration;
        }

        [HttpPost("login")]
        public ActionResult<string> Login([FromBody] User user)
        {
            var existingUser = _dbContext.Users.FirstOrDefault(u => u.Username == user.Username && u.Password == user.Password);

            if (existingUser == null)
            {
                return Unauthorized();
            }

            var claims = new List<Claim> {
                new Claim(ClaimTypes.Name, existingUser.Username),
                new Claim("IsAdmin", existingUser.IsAdmin.ToString())
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                _configuration["Jwt:Issuer"],
                _configuration["Jwt:Issuer"],
                claims,
                expires: DateTime.Now.AddMinutes(30),
                signingCredentials: credentials
            );

            return Ok(new JwtSecurityTokenHandler().WriteToken(token));
        }

        [HttpGet("{id}")]
        [Authorize(Policy = "ViewResource", Resource = "{id}")]
        public ActionResult<Resource> GetResource(int id)
        {
            var resource = _dbContext.Resources.FirstOrDefault(r => r.Id == id);
            if (resource == null)
            {
                return NotFound();
            }

            return Ok(resource);
        }

        [HttpPut("{id}")]
        [Authorize(Policy = "UpdateResource", Resource = "{id}")]
        public ActionResult<Resource> UpdateResource(int id, [FromBody] Resource resource)
        {
            var existingResource = _dbContext.Resources.FirstOrDefault(r => r.Id == id);

            if (existingResource == null)
            {
                return NotFound();
            }

            existingResource.Value = resource.Value;

            _dbContext.SaveChanges();

            return Ok(existingResource);
        }
    }

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            // 添加身份验证服务
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options => {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = Configuration["Jwt:Issuer"],
                        ValidAudience = Configuration["Jwt:Issuer"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
                    };
                });

            // 添加授权服务
            services.AddAuthorization(options => {
                options.AddPolicy("ViewResource", policy =>
                    policy.Requirements.Add(new ViewResourceRequirement())
                        .HandlerType = typeof(ResourceAccessHandler)
                );

                options.AddPolicy("UpdateResource", policy =>
                    policy.Requirements.Add(new UpdateResourceRequirement())
                        .HandlerType = typeof(ResourceAccessHandler)
                );
            });

            // 添加数据库上下文
            services.AddDbContext<AppDbContext>(options =>
                options.UseInMemoryDatabase(databaseName: "SecureApi")
            );

            // 添加控制器
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // 启用身份验证中间件
            app.UseAuthentication();

            app.UseRouting();

            // 启用授权中间件
            app.UseAuthorization();

            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
            });
        }
    }
}

在上面的代码中,我们创建了一个用户和资源数据模型以及AppDbContext类。我们还定义了ViewResourceRequirement和UpdateResourceRequirement授权要求,以及ResourceAccessHandler处理程序。

我们使用AddJwtBearer方法配置JWT身份验证服务,并使用UseAuthentication方法启用身份验证中间件。我们还将授权服务添加到ConfigureServices方法中,并配置了两个授权策略:"ViewResource"和"UpdateResource"。

最后,我们添加了两个API端点:GetResource和UpdateResource,并使用[Authorize]特性对它们进行了保护。

posted @ 2023-04-18 22:41  白日梦想家_zery  阅读(34)  评论(0编辑  收藏  举报