C# 身份3 MVC 6中的授权策略
我做了很多研究,但仍然不确定我是否做得正确。 我找到的最好的资源就在这里 给定一个扩展为包含授权帐号列表的ApplicationUser类,我想限制用户仅查看基于其授权帐号的对账单(和其他操作)。我认为这是一个非常常见的设计,但是网上的大多数文章都提到了以前版本的identity (PS我正在控制器构造函数中注入UserManager) 这是我的行动C# 身份3 MVC 6中的授权策略,c#,asp.net-mvc,asp.net-identity,C#,Asp.net Mvc,Asp.net Identity,我做了很多研究,但仍然不确定我是否做得正确。 我找到的最好的资源就在这里 给定一个扩展为包含授权帐号列表的ApplicationUser类,我想限制用户仅查看基于其授权帐号的对账单(和其他操作)。我认为这是一个非常常见的设计,但是网上的大多数文章都提到了以前版本的identity (PS我正在控制器构造函数中注入UserManager) 这是我的行动 public IActionResult GetStatement(int accountNo,DateTime startDate,DateT
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();
}
我不禁觉得还有更好的办法?
基本上,我想根据操作参数“accountNo”进行授权
任何关于采取何种方法的提示。在本例中,您将使用基于资源的方法,帐户就是资源。这方面的文档位于 首先,您需要定义一个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);
}
}
然后,在控制器中,加载帐户资源后,您将执行以下操作
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();
}
}
公共异步任务视图(int accountId)
{
Account=accountManager.Find(accountId);
如果(帐户==null)
{
返回新的HttpNotFoundResult();
}
if(wait_authorizationService.authorizationAsync(用户、帐户、操作.读取))
{
返回视图(帐户);
}
其他的
{
返回新的ChallengeResult();
}
}
如果您希望以允许将授权策略用于[Authorize]
属性的方式定义授权策略,您可以更改所看到的方法:
这样做的缺点是,您需要确保使用该属性的所有操作都以一致的方式执行,即每次对操作参数或路由参数使用相同的名称
@blowdart在控制器操作中使用
IAAuthorizationService
的示例演示了一种使用和重新使用策略的方法,该策略允许参数名称与策略本身分离。虽然我们可以看到,IAuthorizationService
没有提供强类型的泛型方法,但它似乎提供了一种不太脆弱的方法来实现基于资源的策略。这看起来很有趣,属性是否类似于[Authorize(“AccessByAccountNumber”)]非常感谢BTW解析请求值的问题通常是它们没有那么有用。资源本身将保存决策的信息,例如文档有一个author字段,这就是为什么我们不推荐该路线。在这种情况下,这是可行的,因为用户对象持有一个账号列表,而不是账户持有一个授权用户列表,这更为典型。很好的一点,一旦你离开了最简单的情况,请求可能就没有你做出决定所需的一切。我没想过。有一件事需要注意——授权不是身份的一部分。这是完全独立的:)好的,今天就实施。我对DI相当陌生,但在本例中,我对服务.AddInstance(newauthorization.AccountAuthorizationHandler())有问题代码>如果不通过usermanager,我似乎无法实例化它。但我认为授权处理程序对其自己的DI进行了排序?UserManager使用DbContext时是否对Singleton安全?好的,我仍然被卡住了-IAuthorizationHandler只包含句柄而不包含AuthorizationAsync。我已经发送了一封关于user manager的电子邮件。为什么希望处理程序具有Authorize async?您正在将AuthorizationService注入控制器中-看到了吗?是的,我试图将处理程序而不是IAAuthorizationService注入控制器中。对不起。我想我已经读了好几遍刚才从我身边经过的文件了。
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();
}
}
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'
});
});
});