在使用 ASP.NET Core 构建基于角色的 Web API 时,代码优先方法是一种强大而高效的方法。使用它,我们可以在代码中定义数据模型和关系,然后自动生成相应的数据库模式。这会带来什么?当然是更快的开发周期和更大的灵活性。为什么?因为可以快速轻松地更改数据模型,而无需直接修改数据库模式。 您可以在 swagger.io 上阅读有关设计优先和代码优先方法的更多信息。
在本教程中,我们将介绍使用 ASP.NET Core 6 创建基于角色的 Web API 的步骤。我们将使用 Swagger UI 来可视化并与我们的端点以及作为数据库的 MS SQL Server 进行交互。该应用程序将包含一个身份验证模块和一个事件模块。登录用户将能够查看与其帐户关联的事件,而具有管理员角色的用户可以创建、更新和删除事件。
示例下载:https://download.csdn.net/download/hefeng_aspnet/91490040
让我们开始吧!
项目设置
首先,我们需要设置项目。打开 Visual Studio,创建一个新项目,然后选择 ASP.NET Core Web API。
选择应用程序的名称,然后单击“下一步”。
设置 API 数据库
初始化应用程序后,我们需要配置数据库。我们将使用 EntityFrameworkCore 作为 ORM ,以便它帮助我们管理数据库。因此,我们需要安装一些软件包。
成功安装软件包后,下一步要做的是创建 DbContext。创建 DataContext.cs 文件并继承 DBContext 类。在这里我们将定义表。
public class DataContext: DbContext
{
public DataContext(DbContextOptions options): base(options)
{
}
//Define our tables
}
然后,我们打开 Program.cs 文件并添加 dbContext。我们需要指定 来自 appsettings.json 文件的 dbProvider和连接字符串。 dbProvider 可以是 SqlServer、MySql 或 InMemory。
// Add Db context
var dbProvider = builder.Configuration.GetConnectionString("Provider");
builder.Services.AddDbContext < DataContext > (options =>
{
if (dbProvider == "SqlServer")
{
options.UseSqlServer(builder.Configuration.GetConnectionString("SqlServerConnectionString"));
}
});
确保已 在 appsettings.json文件中添加了ConnectionString 和 Provider ,如下所示:
…
"ConnectionStrings": {
"Provider": "SqlServer",
"SqlServerConnectionString": "Data Source=(localdb)\\MSSQLLocalDB;Database=HRApplication2;Integrated Security=True;Connect Timeout=30; "
},
…
配置 DbContext后,需要生成数据库模型。在本例中,我们需要两个实体(User 和 Event)以及第三个表(UserEvent)来建立它们之间的多对多关系。为此,建议创建一个 Models 文件夹,并在其中创建一个 DbModels 子文件夹,用于创建数据库实体。
让我们从 用户 模型开始。每个用户都应该有一个唯一的 ID、电子邮件、名字、姓氏、密码(将以哈希格式存储)、角色(在演示中可以是用户或管理员)以及 与UserEvent表 关联的 UserEvents 。
public class User
{
public string UserId { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string Role { get; set; }
public IList <UserEvent> UserEvents { get; set; }
}
事件模型还应具有唯一的 ID、标题、类别、日期以及与 UserEvents 表的关系。
public class Event
{
public string Id { get; set; }
public string Title { get; set; }
public string Category { get; set; }
public DateTime Date { get; set; }
public IList <UserEvent> UserEvents { get; set; }
}
由于一个用户可以参加多个活动,并且一个活动也可以由多个用户参加,因此我们需要在这些实体之间建立多对多关系。为此,我们将创建一个名为 UserEvents的附加表。该表将包含 UserId 和 EventId列,用于建立用户实体 和 事件实体 之间的关系 。
public class UserEvent
{
public string UserId { get; set; }
public User User { get; set; }
public string EventId { get; set; }
public Event Event { get; set; }
}
创建数据库模型后,下一步就是在 DbContext中注册它们。为此,我们可以导航到 DataContext.cs 文件,将所有实体添加为 DbSets,并声明关系和主键。这可以通过重写 OnModelCreating 方法并使用 Fluent API 配置关系和键来实现。完成后,结果应如下所示:
public class DataContext: DbContext
{
public DataContext(DbContextOptions options): base(options)
{
}
public DbSet <User> Users { get; set; }
public DbSet < Event > Events { get; set; }
public DbSet < UserEvent > UserEvents { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>()
.HasKey(u => new {
u.UserId
});
builder.Entity<Event>()
.HasKey(e => new {
e.Id
});
builder.Entity<UserEvent>()
.HasKey(ue => new {
ue.UserId, ue.EventId
});
builder.Entity<UserEvent>()
.HasOne(ue => ue.User)
.WithMany(user => user.UserEvents)
.HasForeignKey(u => u.UserId);
builder.Entity<UserEvent>()
.HasOne(uc => uc.Event)
.WithMany(ev => ev.UserEvents)
.HasForeignKey(ev => ev.EventId);
}
}
在我们准备好数据库设计之后,我们应该生成一个将创建数据库的初始迁移。
打开包管理器控制台 并写入命令:
添加迁移初始创建
成功执行后,我们应该使用以下命令更新数据库:
更新数据库
然后使用 Microsoft SQL Management Studio,您应该会看到新创建的数据库。
配置 AutoMapper
AutoMapper 会帮助我们将一个模型转换为另一个模型。这会将输入模型转换为 dbModel。 我们这样做的原因是,我们可能不需要将一个模型的所有属性都包含在另一个模型中。您将在本教程的后面部分看到我们如何使用 AutoMapper。在此之前,我们需要先配置它。 您可以在官方文档中找到更多关于 AutoMapper 的详细说明。
首先,我们必须安装 AutoMaper NuGet 包。之后,我们可以生成一个 MappingProfiles.cs 文件来定义所有映射。为了便于组织,建议将此文件创建在 Helpers 文件夹下。
为了声明映射, MappingProfiles 应该继承 Profile 类,并且我们可以使用 CreateMap<from, to>() 方法声明映射。如果我们需要反向映射模型,可以添加 .ReverseMap() 方法。
一旦我们完成映射,我们必须导航到 Program.cs 文件并 使用我们的 MappingProfiles注册AutoMapper。
… var config = new MapperConfiguration(cfg => { cfg.AddProfile(new MappingProfiles()); }); var mapper = config.CreateMapper(); builder.Services.AddSingleton(mapper); …
设置身份验证
我们将使用 JWT 令牌进行身份验证。它们为我们提供了一种以 JSON 对象形式在各方之间安全地传输信息的方法。您可以 在此处阅读有关 JWT 令牌的更多信息。要使用它们,我们必须首先安装必要的 NuGet 包。我们需要 Microsoft.IdentityModel.Tokens 和 Microsoft.AspNetCore.Authentication.JwtBearer。
接下来,我们必须在appsettings.json 文件中定义一些 token 配置 。这些配置包括 Issuer、Audience 和 SecretKey。
"Jwt": { "Issuer": "https://localhost:7244/", "Audience": "https://localhost:7244/", "Key": "S1u*p7e_r+S2e/c4r6e7t*0K/e7y" }
定义令牌配置后,我们可以在 Program.cs 文件中配置 JWT 服务。这涉及指定将使用的架构以及任何必要的验证参数。
… builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey (Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])), ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = false, ValidateIssuerSigningKey = true }; }); …
确保您还添加了 app.UseAuthentication();
设置Swagger
为了使用 Swagger UI测试我们的应用程序端点,我们必须 在 Program.cs文件中包含app.UseSwaggerUI() 。
之后,我们必须生成一个 AuthResponse 过滤器,以便使用 JWT 令牌测试已验证的端点。为此,我们可以创建一个 实现 IOperationFilter接口的AuthResponsesOperationFilter类 。Apply 方法应该包含将 AuthResponse 过滤器添加到 Swagger 所需的逻辑。
public class AuthResponsesOperationFilter: IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) .OfType<AuthorizeAttribute>(); if (authAttributes.Any()) { var securityRequirement = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new List<string>() } }; operation.Security = new List<OpenApiSecurityRequirement> { securityRequirement }; operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" }); } } }
之后,确保已在 Program.cs .AddSwaggerGen 方法中将过滤器添加为选项。
builder.Services.AddSwaggerGen(option => { option.SwaggerDoc("v1", new OpenApiInfo { Title = "Northwind CRUD", Version = "v1" }); option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Please enter a valid token", Name = "Authorization", Type = SecuritySchemeType.Http, BearerFormat = "JWT", Scheme = "bearer" }); option.OperationFilter < AuthResponsesOperationFilter > (); } );
您可以在官方文档中阅读“什么是 Swagger?”的更详细解释 。
注册端点
完成配置后,我们可以继续创建注册端点。第一步是生成一个 RegisterInputModel.cs 文件,该文件位于 Models/InputModels 文件夹下。
注册过程需要 Email、FirstName、LastName、Password 和 ConfirmedPassword 字段。所有这些字段都是必填项,因此我们将添加 [Required] 属性。此外,我们还将为 Email 字段添加 [EmailAddress] 属性。我们可以根据需要添加其他属性,例如最小长度和最大长度。但出于演示目的,我们将仅使用这些属性。
public class RegisterInputModel { [EmailAddress] public string Email { get; set; } [Required] public string FirstName { get; set; } [Required] public string LastName { get; set; } [Required] public string Password { get; set; } [Required] public string ConfirmedPassword { get; set; } }
接下来,我们必须向MappingProfiles.cs文件添加一个映射 ,以便在RegisterInputModel 和 User模型 之间实现 双向转换。
创建映射<RegisterInputModel,用户>().ReverseMap();
为了保持关注点分离,我们将创建一个 Services 文件夹。每个模块都有自己的服务用于与数据库交互。我们可以先生成一个 AuthService.cs 文件,并注入 DataContext 和 Configuration。
AuthService.cs中的第一个方法 应该是 GenerateJwtToken,它将电子邮件和角色作为参数并返回包含用户信息的 JWT 令牌。
public string GenerateJwtToken(string email, string role) { var issuer = this.configuration["Jwt:Issuer"]; var audience = this.configuration["Jwt:Audience"]; var key = Encoding.ASCII.GetBytes(this.configuration["Jwt:Key"]); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new [] { new Claim("Id", Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Sub, email), new Claim(JwtRegisteredClaimNames.Email, email), new Claim(ClaimTypes.Role, role), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }), Expires = DateTime.UtcNow.AddMinutes(5), Issuer = issuer, Audience = audience, SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) }; var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); }
为了对密码进行哈希处理,我们将使用 BCrypt.Net.BCrypt。首先,我们必须安装该包并将其作为 using 语句添加到文件开头。
using BC = BCrypt.Net.BCrypt;
之后,我们将创建几个辅助方法。其中一个将验证具有给定电子邮件的用户是否存在,另一个将对用户进行身份验证,另外两个将通过电子邮件和 ID 获取用户。
public bool IsAuthenticated(string email, string password) { var user = this.GetByEmail(email); return this.DoesUserExists(email) && BC.Verify(password, user.Password); } public bool DoesUserExists(string email) { var user = this.dataContext.Users.FirstOrDefault(x => x.Email == email); return user != null; } public User GetById(string id) { return this.dataContext.Users.FirstOrDefault(c => c.UserId == id); } public User GetByEmail(string email) { return this.dataContext.Users.FirstOrDefault(c => c.Email == email); }
在创建register方法之前,我们必须先创建一个方法来生成唯一的ID。该方法可以定义如下:
public class IdGenerator { public static string CreateLetterId(int length) { var random = new Random(); const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); } }
现在我们可以继续实现 Register 方法了。在这个方法中,我们将生成一个唯一的 ID,检查它是否已经存在,如果存在,则生成一个新的。然后,我们将对用户密码进行哈希处理,并将新用户添加到数据库中。
public User RegisterUser(User model) { var id = IdGenerator.CreateLetterId(10); var existWithId = this.GetById(id); while (existWithId != null) { id = IdGenerator.CreateLetterId(10); existWithId = this.GetById(id); } model.UserId = id; model.Password = BC.HashPassword(model.Password); var userEntity = this.dataContext.Users.Add(model); this.dataContext.SaveChanges(); return userEntity.Entity; }
如果您尚未创建 AuthController ,现在是时候了。转到 Controllers 文件夹并添加 AuthController ,它应该继承自 Controller 类。我们还应该添加 [ApiController] 属性和 [Route( “[controller]” )] ,以便 Swagger 识别它。
之后,我们应该注入 mapper、authService 和 logger(如果使用的话),并创建 RegisterMethod。它应该只允许未经身份验证的用户通过 post 请求访问。它应该接受 RegisterInputModel 作为参数,并检查 ModelState是否 有效。如果有效,它将为该用户生成 JWT 令牌。整个方法应该如下所示:
[AllowAnonymous] [HttpPost("Register")] public ActionResult<string> Register(RegisterInputModel userModel) { try { if (ModelState.IsValid) { if (userModel.Password != userModel.ConfirmedPassword) { return BadRequest("Passwords does not match!"); } if (this.authService.DoesUserExists(userModel.Email)) { return BadRequest("User already exists!"); } var mappedModel = this.mapper.Map<RegisterInputModel, User>(userModel); mappedModel.Role = "User"; var user = this.authService.RegisterUser(mappedModel); if (user != null) { var token = this.authService.GenerateJwtToken(user.Email, mappedModel.Role); return Ok(token); } return BadRequest("Email or password are not correct!"); } return BadRequest(ModelState); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
登录功能
登录功能类似,只是我们需要在数据库中搜索用户。首先,我们应该创建 LoginInputModel.cs 文件,该文件只包含 Email 和 Password 字段。别忘了在 MappingProfiles.cs文件中添加该文件 ,否则将无法正常工作。
public class LoginInputModel { [EmailAddress] [Required] public string Email { get; set; } [Required] public string Password { get; set; } }
然后在 AuthController.cs中 创建 Login 方法,该方法接受 LoginInputModel 作为参数,并检查用户是否已通过身份验证。如果已通过身份验证,则生成一个 token。否则,返回错误。
[AllowAnonymous] [HttpPost("Login")] public ActionResult <string> Login(LoginInputModel userModel) { try { if (ModelState.IsValid) { if (this.authService.IsAuthenticated(userModel.Email, userModel.Password)) { var user = this.authService.GetByEmail(userModel.Email); var token = this.authService.GenerateJwtToken(userModel.Email, user.Role); return Ok(token); } return BadRequest("Email or password are not correct!"); } return BadRequest(ModelState); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
为事件添加 CRUD
完成身份验证后,我们可以开发事件的端点。我们将创建完整的 CRUD 操作。与用户操作类似,我们应该创建 EventService.cs 文件。该文件将包含以下方法:通过 ID 获取事件、获取特定用户的所有事件、创建新事件、更新现有事件以及删除事件。整个文件应如下所示:
public class EventService { private readonly DataContext dataContext; public EventService(DataContext dataContext) { this.dataContext = dataContext; } public Event[] GetAllForUser(string email) { var user = this.dataContext.Users .FirstOrDefault(user => user.Email == email); return this.dataContext.Events .Include(ev => ev.UserEvents) .Where(e => e.UserEvents.FirstOrDefault(ue => ue.UserId == user.UserId) != null) .ToArray(); } public Event GetById(string id) { return this.dataContext.Events .Include(ev => ev.UserEvents) .FirstOrDefault(c => c.Id == id); } public Event Create(Event model) { var id = IdGenerator.CreateLetterId(6); var existWithId = this.GetById(id); while (existWithId != null) { id = IdGenerator.CreateLetterId(6); existWithId = this.GetById(id); } model.Id = id; var eventEntity = this.dataContext.Events.Add(model); this.dataContext.SaveChanges(); return eventEntity.Entity; } public Event Update(Event model) { var eventEntity = this.dataContext.Events .Include(ev => ev.UserEvents) .FirstOrDefault(c => c.Id == model.Id); if (eventEntity != null) { eventEntity.Title = model.Title != null ? model.Title : eventEntity.Title; eventEntity.Date = model.Date != null ? model.Date : eventEntity.Date; eventEntity.Category = model.Category != null ? model.Category : eventEntity.Category; eventEntity.UserEvents = model.UserEvents.Count! > 0 ? model.UserEvents : eventEntity.UserEvents; this.dataContext.SaveChanges(); } return eventEntity; } public Event Delete(string id) { var eventEntity = this.GetById(id); if (eventEntity != null) { this.dataContext.Events.Remove(eventEntity); this.dataContext.SaveChanges(); } return eventEntity; } }
接下来,您将需要转到控制器并为每个请求设置一个方法。
我们将创建一个 EventBindingModel ,用于存储来自事件模型的所有必要数据。
对于 GetAll 方法,确保它使用 GET 请求并检索用户的令牌、对其进行解码并获取该用户的事件。
[HttpGet] [Authorize] public ActionResult<EventBindingModel[]> GetAll() { try { var userEmail = this.authService.DecodeEmailFromToken(this.Request.Headers["Authorization"]); var events = this.eventService.GetAllForUser(userEmail); return Ok(this.mapper.Map<Event[], EventBindingModel[]> (events)); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } } … public string DecodeEmailFromToken(string token) { var decodedToken = new JwtSecurityTokenHandler(); var indexOfTokenValue = 7; var t = decodedToken.ReadJwtToken(token.Substring(indexOfTokenValue)); return t.Payload.FirstOrDefault(x => x.Key == "email").Value.ToString(); } …
通过id获取也应该是以 id作为参数的GET请求。
[HttpGet("{id}")] [Authorize] public ActionResult<Event> GetById(string id) { try { var eventEntity = this.eventService.GetById(id); if (eventEntity != null) { return Ok(eventEntity); } return NotFound(); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
删除端点将是 DELETE 请求,并且将以 id 作为参数。
[HttpDelete("{id}")] [Authorize(Roles = "Administrator")] public ActionResult<Event> Delete(string id) { try { var eventEntity = this.eventService.Delete(id); if (eventEntity != null) { return Ok(eventEntity); } return NotFound(); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
为了简化添加或更新事件记录的流程,我们创建一个 专门用于创建和更新操作的EventInputModel 。此模型仅需要我们提供用户事件的必要属性,包括标题、类别、日期、用户 ID 和事件 ID。使用此模型,我们无需为每个操作指定 事件 模型的所有属性。
[HttpPost] public ActionResult<Event> Create(EventInputModel model) { try { if (ModelState.IsValid) { var mappedModel = this.mapper.Map < EventInputModel, Event > (model); var eventEntity = this.eventService.Create(mappedModel); return Ok(eventEntity); } return BadRequest(ModelState); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
更新将是 PUT 请求,并且还将以 EventInputModel 作为参数。
[HttpPut] public ActionResult<Event> Update(EventInputModel model) { try { if (ModelState.IsValid) { var mappedModel = this.mapper.Map<EventInputModel, Event>(model); var eventEntity = this.eventService.Update(mappedModel); if (eventEntity != null) { return Ok(eventEntity); } return NotFound(); } return BadRequest(ModelState); } catch (Exception error) { logger.LogError(error.Message); return StatusCode(500); } }
添加基于角色的授权
为了将某些操作限制为特定用户角色,我们可以使用基于角色的授权。例如,在我们的场景中,我们希望将事件的创建、更新和删除端点的访问权限限制为具有管理员角色的用户。
要进行设置,我们需要 在Program.cs文件 中 添加app.UseAuthorization(); 。然后,对于每个需要限制访问的端点,我们将添加 [Authorize] 属性,该属性将指定允许的角色。例如,我们可以确保只有管理员才能访问 Delete 端点。
… [Authorize(Roles = "Administrator")] public ActionResult<Event> Delete(string id) …
创建 DbSeeder
在运行应用程序时,我们经常希望在数据库中预先填充一些数据,无论是出于测试目的还是其他原因。这时就需要使用种子功能了。首先,我们需要定义要使用的数据。
为此,我们可以创建一个 Resources 文件夹并添加两个 JSON 文件:一个用于用户,一个用于事件。这些文件应包含我们想要填充到数据库中的数据。例如,我们的文件可能如下所示:
[ { "UserId": "USERABCDE", "FirstName": "Kate", "LastName": "Lorenz", "Password": "kate.lorenz", "Email": "klorenz@hrcorp.com", "Role": "Administrator" }, { "UserId": "ASERABCDE", "FirstName": "Anthony", "LastName": "Murray", "Password": "anthony.murray", "Email": "amurray@hrcorp.com", "Role": "User" } ]
接下来,我们应该创建一个 包含 Seed 方法的DbSeeder 类。此方法将读取我们之前定义的数据并将其填充到数据库中。为此,我们需要将 dbContext 作为参数传入。
public class DBSeeder { public static void Seed(DataContext dbContext) { ArgumentNullException.ThrowIfNull(dbContext, nameof(dbContext)); dbContext.Database.EnsureCreated(); var executionStrategy = dbContext.Database.CreateExecutionStrategy(); executionStrategy.Execute( () => { using(var transaction = dbContext.Database.BeginTransaction()) { try { // Seed Users if (!dbContext.Users.Any()) { var usersData = File.ReadAllText("./Resources/users.json"); var parsedUsers = JsonConvert.DeserializeObject <User[]>(usersData); foreach(var user in parsedUsers) { user.Password = BC.HashPassword(user.Password); } dbContext.Users.AddRange(parsedUsers); dbContext.SaveChanges(); } // Seed Events if (!dbContext.Events.Any()) { var eventsData = File.ReadAllText("./Resources/events.json"); var parsedEvents = JsonConvert.DeserializeObject <Event[]>(eventsData); dbContext.Events.AddRange(parsedEvents); dbContext.SaveChanges(); } transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); } } }); } }
之后,在我们的 Helpers 文件夹中,我们应该创建一个数据库初始化程序扩展,它将运行 Seed 方法。
public static class DBInitializerExtension { public static IApplicationBuilder UseSeedDB(this IApplicationBuilder app) { ArgumentNullException.ThrowIfNull(app, nameof(app)); using var scope = app.ApplicationServices.CreateScope(); var services = scope.ServiceProvider; var context = services.GetRequiredService < DataContext > (); DBSeeder.Seed(context); return app; } }
最后,我们需要打开 Program.cs 文件并添加 app.UseSeedDB() 方法。这确保我们的应用程序启动时会检查数据库中是否有数据。如果没有,我们之前创建的 Seed 方法将自动使用我们定义的数据填充它。
添加 CORS
为了为我们的端点启用跨域资源共享(CORS),我们需要在 Program.cs 文件中添加一个 cors 服务。在这种情况下,我们将允许从任何区域访问,但如果您愿意,也可以指定特定的域。
builder.Services.AddCors(policyBuilder => policyBuilder.AddDefaultPolicy(policy => policy.WithOrigins("*") .AllowAnyHeader() .AllowAnyHeader()) );
然后添加 app.UseCors(); 方法。
这将允许我们从前端应用程序访问我们的 API。
总结一下……
在构建安全且可扩展的 Web 应用程序时,使用 ASP .NET Core 创建基于角色的 API 至关重要。通过使用基于角色的授权,您可以根据分配给用户的角色来控制对 API 资源的访问。这确保只有授权用户才能访问敏感数据或执行关键操作,从而使您的应用程序更加安全可靠。在本教程中,我们学习了如何从零到一创建一个简单的基于角色的 API。
示例下载:https://download.csdn.net/download/hefeng_aspnet/91490040
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。