我是 .net 和 Angular 的新手,但我发现了我想要的一个例子(动态角色和权限管理和授权),问题是它是一个使用视图的 MVC Web 应用程序,我想将相同的逻辑应用于 Web api,所以我可以用 Angular 来处理前端。 这是示例“aspnet-core 中基于权限的授权”的文章 我开始尝试工作但没有成功。 你能给我关于此事的任何见解吗?
这是我尝试过的一个例子
namespace roles_permissions_mangement.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize(Roles = "SuperAdmin")]
public class RolesController : ControllerBase
{
private readonly RoleManager<IdentityRole> _roleManager;
public RolesController(RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<IdentityRole>>> GetRoles()
{
var roles = await _roleManager.Roles.ToListAsync();
return Ok(roles);
}
[HttpPost]
public async Task<ActionResult> AddRole([FromBody] string roleName)
{
if (roleName != null)
{
await _roleManager.CreateAsync(new IdentityRole(roleName));
return Ok(new { Message = "Role added successfully." });
}
return BadRequest(new { Message = "somthing went wrong" });
}
}
}
namespace roles_permissions_mangement.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize(Roles = "SuperAdmin")]
public class PermissionController : ControllerBase
{
private readonly RoleManager<IdentityRole> _roleManager;
public PermissionController(RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
}
[HttpGet("{roleId}")]
public async Task<ActionResult<PermissionViewModel>> GetRolePermissions(string roleId)
{
var model = new PermissionViewModel();
var allPermissions = new List<RoleClaimsViewModel>();
allPermissions.GetPermissions(typeof(Permissions.Products), roleId);
var role = await _roleManager.FindByIdAsync(roleId);
model.RoleId = roleId;
var claims = await _roleManager.GetClaimsAsync(role);
var allClaimValues = allPermissions.Select(a => a.Value).ToList();
var roleClaimValues = claims.Select(a => a.Value).ToList();
var authorizedClaims = allClaimValues.Intersect(roleClaimValues).ToList();
foreach (var permission in allPermissions)
{
permission.Selected = authorizedClaims.Any(a => a == permission.Value);
}
model.RoleClaims = allPermissions;
return Ok(model);
}
[HttpPost]
public async Task<ActionResult> UpdateRolePermissions([FromBody] PermissionViewModel model)
{
var role = await _roleManager.FindByIdAsync(model.RoleId);
var claims = await _roleManager.GetClaimsAsync(role);
foreach (var claim in claims)
{
await _roleManager.RemoveClaimAsync(role, claim);
}
var selectedClaims = model.RoleClaims.Where(a => a.Selected).ToList();
foreach (var claim in selectedClaims)
{
await _roleManager.AddPermissionClaim(role, claim.Value);
}
return Ok(new { Message = "Role permissions updated successfully." });
}
}
}
namespace roles_permissions_mangement
{
public class Program
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("app");
try
{
var userManager = services.GetRequiredService<UserManager<IdentityUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
await Seeds.DefaultRoles.SeedAsync(userManager, roleManager);
await Seeds.DefaultUsers.SeedBasicUserAsync(userManager, roleManager);
await Seeds.DefaultUsers.SeedSuperAdminAsync(userManager, roleManager);
logger.LogInformation("Finished Seeding Default Data");
logger.LogInformation("Application Starting");
}
catch (Exception ex)
{
logger.LogWarning(ex, "An error occurred seeding the DB");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
namespace roles_permissions_mangement
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "roles_permissions_mangement", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "roles_permissions_mangement v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
我知道这是错误的,所以我将非常乐意提供任何帮助,或者如果您有任何其他方法可以对 Angular 和 .net 执行相同的操作,请告诉我。
如果您可以在此处添加更多关于您想要实现的目标的详细信息,将会很有帮助。那么答案可能会更有针对性,更少的假设。
我只是超出了教程,但权限不是在控制器的服务器端处理的,而是在视图中处理的。因此它基本上依赖于服务器渲染的 razor 页面来工作,并且您将无法使用 Angular 应用程序获得相同的结果。尽管您可以从服务器请求用户的权限并相应地呈现您的菜单,但它根本没有安全优势,因为用户仍然可以随心所欲地操纵网站。毕竟它只是 Javascript。
话虽这么说,您仍然需要根据权限策略来保护您的控制器操作。即使在 Razor 页面中,服务器端或客户端组件的条件渲染也不会阻止任何人直接调用控制器操作。因此,您最终肯定必须将某些内容硬编码到您的服务器中。在这种情况下,权限而不是角色。虽然权限方法更加灵活,但它也给整个授权过程增加了更多的复杂性。根据经验,我可以告诉您,A 维护基于许可的授权可能会非常痛苦。
首先,你应该问自己是否真的需要这种灵活的方法。您是否有许多不同的用户类型和许多不同的权限,或者您是否有例如管理员是否应该能够以精细的方式处理每个用户的权限?在我们的例子中,我们有基本用户,可以为其公司添加具有许多不同权限的子用户。所以我们只有几个角色,权限直接与用户相关。
因此,如果您没有类似的需求,那么在十分之九的情况下,基于角色的方法就足够了,并且可以为您省去很多麻烦。
话虽这么说,代码实际上应该大部分工作。您只需要为您的 Angular 应用程序使用不同类型的登录即可。我本人从未使用过 Identity for .Net Core。我们通常在简单的情况下实现一个简单的自定义 JWT 令牌提供程序、一个功能齐全的身份服务器或像 authO 这样的第三方解决方案。所以我不能真正帮助你,但这将是前进的方向。如何使 Asp.Net 身份登录与 Angular 一起使用。除此之外,控制器只为授权的超级管理员返回数据,您可以在 Angular 中以相同的方式处理这些数据。