Identity 3 MVC 6中的授权策略

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

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”

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

在这种情况下,您将使用基于资源的帐户作为资源。 相关文档位于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(); } 

在您的控制器中,您注入AuthorizationService;

 public class AccountController : Controller { IAuthorizationService _authorizationService; public AccountController(IAuthorizationService authorizationService) { _authorizationService = authorizationService; } } 

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

 public async Task 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(); } } 

如果要以允许将其用于[Authorize]属性的方式定义授权策略,则可以更改本文中的方法:

 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' }); }); }); 

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

@ blowdart在控制器操作中使用IAuthorizationService的示例演示了一种使用和重用策略的方法,该策略允许参数名称与策略本身分离。 虽然我们可以看到IAuthorizationService不提供强类型generics方法,但它似乎提供了一种不太脆弱的方法来实现基于资源的策略。