Identity 3 MVC 6中的授权策略

时间:2015-12-15 15:30:46

标签: c# asp.net-mvc asp.net-identity

我做了很多研究,但我仍然不确定我是否正确地做了这件事。 我找到的最好的资源是

http://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/

鉴于ApplicationUser类已扩展为包含授权帐号列表,我希望将用户限制为仅在其授权帐户上查看语句(以及其他基于操作)。我认为这是一个非常常见的设计,但网上的大多数文章都提到了以前版本的身份。

(PS我在Controller构造函数中注入UserManager)

这是我的行动

public IActionResult GetStatement(int accountNo,DateTime startDate,DateTime endDate)
{
    var user = userManager.Users
        .Include(u => u.AuthorisedAccounts)
        .Where(u => u.Id == User.GetUserId())
        .FirstOrDefault();
    if (user.AuthorisedAccounts != null)
    {
        foreach (var account in user.AuthorisedAccounts)
        {
            if (account.AccountNo == accountNo)
                return View(statementService.GetStatement(accountNo, startDate, endDate, 0));
        }
    }
    return HttpUnauthorized();
}

我不能帮助感觉有更好的方法吗?  基本上我想基于action参数进行授权。“accountNo”

有关采取何种方法的任何提示。

2 个答案:

答案 0 :(得分:3)

在这种情况下,您将使用基于资源的帐户作为资源。相关文档位于https://docs.asp.net/en/latest/security/authorization/resourcebased.html

首先,您要定义Read,

的操作
public static class Operations
{
    public static OperationAuthorizationRequirement Read =
        new OperationAuthorizationRequirement   { Name = "Read" };
}

现在您已经有了AccountAccess政策

public class AccountAuthorizationHandler : AuthorizationHandler<
    OperationAuthorizationRequirement, Account>
{
    IUserManager _userManager;

    public AccountAuthorizationHandler(IUserManager userManager)
    {
        _userManager = userManager;
    }

    protected override void Handle(AuthorizationContext context,
                                   OperationAuthorizationRequirement requirement,
                                   Account resource)
    {
        // Pull the user ID claim out from the context.User
        var userId = context.User.....
        // Get the current user's account numbers.       
        var user = userManager.Users
            .Include(u => u.AuthorisedAccounts)
            .Where(u => u.Id == userId)
            .FirstOrDefault();
    }

    // Now check if the user's account numbers match the resource accountNumber, and 
    // also check the operation type, in case you want to vary based on create, view etc.
    if (user.AuthorisedAccounts.Contains(resource.AccountId &&
        requirement.Name == "View")
   {
      context.Succeed(requirement);
   } 
}

之后在配置服务中的DI容器中注册您的策略;

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddAuthorization();

    services.AddSingleton<IAuthorizationHandler,
                          AccountAuthorizationHandler>();
}

在您的控制器中注入AuthorizationService;

public class AccountController : Controller
{
    IAuthorizationService _authorizationService;

    public AccountController(IAuthorizationService authorizationService)
    {
        _authorizationService = authorizationService;
    }
}

然后,在您的控制器中,在您加载帐户资源后,您可以执行类似

的操作
public async Task<IActionResult> View(int accountId)
{
    Account account = accountManager.Find(accountId);

    if (account == null)
    {
        return new HttpNotFoundResult();
    }

    if (await _authorizationService.AuthorizeAsync(User, account, Operations.Read))
    {
        return View(account);
    }
    else
    {
        return new ChallengeResult();
    }
}

答案 1 :(得分:0)

如果您希望以允许您将其用于UIViewContentModeScaleAspectFill属性的方式定义授权策略,则可以更改Apple docs所见的方法:

[Authorize]

这样做的缺点是,您需要确保使用该属性的所有操作以一致的方式执行,即每次使用相同的action参数或路由参数名称。

@ blowdart在控制器操作中使用services.AddAuthorization(options => { // inline policies options.AddPolicy("AccessByAccountNumber", policy => { policy.RequireDelegate((context, requirement) => { var httpContext = (context as dynamic).HttpContext; // Proceed to grab the account number from the request values // and compare it against the user object stored in 'context.User' }); }); }); 的示例演示了一种使用和重用策略的方法,该策略允许参数名称与策略本身分离。虽然我们可以看到IAuthorizationService没有提供强类型泛型方法,但它似乎提供了一种不太脆弱的方法来实现基于资源的策略。