繁体   English   中英

有没有比使用IAsyncActionFilter更好的方法来授权用户是否在角色中或用户ID是否在数据库中用于特定记录

[英]Is there a better way than using an IAsyncActionFilter to authorize if user is in role or user id is in database for specific record

要求:有些控制器方法只有在以下情况下才能调用:

1.用户具有“TaskAdmin”角色

要么

2.用户负责将在控制器方法中修改的数据库对象(只有一个列具有要比较的用户ID)。 此数据表中的记录可以更改,而不是“硬编码”。

我知道解决这个问题的两种可能性:

  1. 创建2个方法。 一个具有属性[Authorize(Roles = "TaskAdmin")] ,并且将检查用户是否负责数据库对象。

  2. 创建一个IAsyncActionFilter ,它检查要求和要在控制器方法上使用的TypeFilterAttribute

有没有更好的方法(使用ASP.NET Core)?

有没有更好的方法(使用ASP.NET Core)?

是。 您可以使用基于策略的授权来实现基于权限的复杂规则。

public class RecordOwnerRequirement : IAuthorizationRequirement
{
}

public class RecordOwnerHandler : AuthorizationHandler<RecordOwnerRequirement>
{
    private readonly ApplicationDbContext dbContext;
    private readonly IActionContextAccessor actionContextAccessor;

    public RecordOwnerHandler(ApplicationDbContext dbContext, IActionContextAccessor actionContextAccessor)
    {
        this.dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
        this.actionContextAccessor = actionContextAccessor ?? throw new ArgumentNullException(nameof(actionContextAccessor));
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RecordOwnerRequirement requirement)
    {
        if (IsUserAuthorized(context))
        {
            context.Succeed(requirement);
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }

    private bool IsUserAuthorized(AuthorizationHandlerContext context)
    {
        var id = this.actionContextAccessor.ActionContext.RouteData.Values["id"];

        // Use the dbContext to compare the id against the database...

        // Return the result
        return true;
    }
}

Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    //*********************************************************************
    // Add policy for record owner 
    services.AddAuthorization(options =>
    {
        options.AddPolicy("RecordOwner", policy =>
            policy.Requirements.Add(new RecordOwnerRequirement()));
    });
    //*********************************************************************

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    //*********************************************************************
    // Register record owner handler with the DI container 
    services.AddTransient<IAuthorizationHandler, RecordOwnerHandler>();
    services.AddTransient<IActionContextAccessor, ActionContextAccessor>();
    //*********************************************************************

    services.AddMvc();
}

用法

public class HomeController : Controller
{
    [Authorize(Roles = "TaskAdmin", Policy = "RecordOwner")]
    public IActionResult Contact()
    {
        ViewData["Message"] = "Your contact page.";

        return View();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM