我在ASP.NET Core中使用Angular和ASP.NET Identity应用程序。
我有以下控制器操作
[HttpGet("users/{userId:int:min(1)}/notes"), Authorize]
public async Task<IActionResult> GetNotesBy(userId) {
var data = _service.getNotesBy(userId);
return Ok(data);
} // GetNotesBy
我想限制对API的访问:
如果用户通过身份验证,则只能访问其备注。 我想阻止ID = X的身份验证用户访问ID = Y的用户的注释。在这种情况下如何阻止用户?
答案 0 :(得分:3)
这是基于资源的授权的目标。
由于基于资源的授权需要在控制器内部强制执行所需的实际资源。
以下内容适用于ASP.NET Core RC1。
所以,我们假设你的getNotesBy返回一个Notes
类,你有一些操作,读,写,更新,删除。
首先我们需要定义操作。 Microsoft.AspNet.Authorization.Infrastructure
,OperationAuthorizationRequirement
中有一个合适的基类。所以我们会做这样的事情。
public static class Operations
{
public static OperationAuthorizationRequirement Create =
new OperationAuthorizationRequirement { Name = "Create" };
public static OperationAuthorizationRequirement Read =
new OperationAuthorizationRequirement { Name = "Read" };
public static OperationAuthorizationRequirement Update =
new OperationAuthorizationRequirement { Name = "Update" };
public static OperationAuthorizationRequirement Delete =
new OperationAuthorizationRequirement { Name = "Delete" };
}
现在我们有了我们的业务,我们考虑如何处理授权。如果当前用户拥有笔记,或者当前用户是管理员,则操作可以有两种方式成功。这相当于单个需求/操作的两个处理程序。
管理员很容易,看起来像这样;
public class AdminAuthorizationHander :
AuthorizationHandler<OperationAuthorizationRequirement, Notes>
{
protected override void Handle(AuthorizationContext context,
OperationAuthorizationRequirement requirement,
Document resource)
{
var isSuperUser = context.User.FindFirst(c => c.Type == "Superuser" &&
c.Value == "True");
if (isSuperUser != null)
{
context.Succeed(requirement);
return;
}
}
}
这里我们正在寻找值为True的超级用户声明。如果现在我们成功了这个要求。您可以从方法签名中看到我们正在使用OperationAuthorizationRequirement和一个资源Notes类。此处理程序不会将自身限制为单个操作,管理员对每个操作都有权限。
现在我们可以编写查找实际用户的处理程序。
public class NotesAuthorizationHandler :
AuthorizationHandler<OperationAuthorizationRequirement, Notes>
{
protected override void Handle(AuthorizationContext context,
OperationAuthorizationRequirement requirement,
Notes resource)
{
if (context.User.Name == resource.Owner)
{
context.Succeed(requirement);
}
}
}
这里我们正在编写适用于所有资源的内容,并根据当前用户的名称检查资源上的Owner属性。
因此,我们现在有两个处理程序用于单个要求,OperationAuthorizationRequirement
。
现在我们需要注册我们的处理程序。在startup.cs
中,您在ConfigureServices()
方法中在DI中注册处理程序。致电services.AddAuthorization()
后,您需要将处理程序放入DI中。你会这样做;
services.AddSingleton<IAuthorizationHandler, AdminAuthorizationHandler>();
services.AddSingleton<IAuthorizationHandler, NotesAuthorizationHandler>();
如果您正在使用Singleton
之类的内容,则可以将范围从DbContext
调整为您喜欢的范围。
最后我们几乎准备好调用它,但首先你需要更改控制器构造函数以获取IAuthorizationService
的实例。完成后,您可以致电AuthorizeAsync()
然后离开。
[Authorize]
public class NotesController : Controller
{
IAuthorizationService _authorizationService;
public NotesController(IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
[HttpGet("users/{userId:int:min(1)}/notes"), Authorize]
public async Task<IActionResult> GetNotesBy(userId)
{
var resource = _service.getNotesBy(userId);
if (await authorizationService.AuthorizeAsync(User, resource, Operations.Read))
{
return Ok(data);
}
return new ChallengeResult();
}
}
所以你正在做的是获取你的资源,然后根据它和操作授权当前用户。发生这种情况时,将调用可以处理该资源和操作的所有处理程序。由于有多个处理程序,任何人都可以成功并允许访问。