Ham*_*lar 5 c# asp.net authorization asp.net-core
按照这里的文档,我尝试实现基于策略的身份验证方案.http://docs.asp.net/en/latest/security/authorization/policies.html#security-authorization-handler-example
我遇到的问题是我的自定义AuthorizationHandler没有调用我的Handle方法.(它不会扔到这里).它还会在构造函数中注入当前的依赖项.
这是AuthorizationHandler代码.
using WebAPIApplication.Services;
using Microsoft.AspNet.Authorization;
namespace WebAPIApplication.Auth
{
public class TokenAuthHandler : AuthorizationHandler<TokenRequirement>, IAuthorizationRequirement
{
private IAuthService _authService;
public TokenAuthHandler(IAuthService authService)
{
_authService = authService;
}
protected override void Handle(AuthorizationContext context, TokenRequirement requirement)
{
throw new Exception("Handle Reached");
}
}
public class TokenRequirement : IAuthorizationRequirement
{
public TokenRequirement()
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
在启动我有
// Authorization
services.AddSingleton<IAuthorizationHandler, TokenAuthHandler>()
.AddAuthorization(options =>
{
options.AddPolicy("ValidToken",
policy => policy.Requirements.Add(new TokenRequirement()));
});
Run Code Online (Sandbox Code Playgroud)
控制器方法是
// GET: api/values
[HttpGet, Authorize(Policy="ValidToken")]
public string Get()
{
return "test";
}
Run Code Online (Sandbox Code Playgroud)
点击此端点不返回任何内容,并且控制台中有警告
warn: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[0]
Authorization failed for the request at filter 'Microsoft.AspNet.Mvc.Filters.AuthorizeFilter'.
Run Code Online (Sandbox Code Playgroud)
我能够点击其他没有成功属性的端点.
SOS,杰克
Ben*_*ers 13
我把它放在这里供参考,因为我花了太长时间搞清楚这一点......
我已经实现了一个自定义需求和处理程序(为测试而空了):
using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;
public class TestHandler : AuthorizationHandler<TestRequirement>, IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TestRequirement requirement)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
}
public class TestRequirement : IAuthorizationRequirement
{
}
Run Code Online (Sandbox Code Playgroud)
在我的Startup.cs ConfigureServices()部分注册:
services.AddAuthorization(options =>
{
options.AddPolicy("Test", policy => policy.Requirements.Add(new TestRequirement()));
// Other policies here
}
Run Code Online (Sandbox Code Playgroud)
将它添加到我的控制器方法:
[HttpGet]
[Authorize(Policy = "Test")]
public IActionResult Index()
{
Return View();
}
Run Code Online (Sandbox Code Playgroud)
但是每次请求控制器方法都会收到403错误(不是401)!
事实证明,我没有注册TestHandler与ConfigureServices()的(依赖注入)部分Startup.cs.
services.AddSingleton<IAuthorizationHandler, TestHandler>();
Run Code Online (Sandbox Code Playgroud)
希望这可以避免某人在他们的桌子上敲头.:|
对 adem caglin 的评论中提到了这个问题的答案,所以支持他。
问题是在调用AuthorizeFilter之前拒绝请求。AuthorizationHandler这是因为对于Authorize标签的每次使用,MVC 都会在管道中添加AuthorizeFilter到前面。AuthorizationHandler这AuthorizeFilter将检查当前用户身份是否已获得授权。就我而言,没有与任何用户关联的授权身份,因此这总是会失败。
一个解决方案(IMO 有点 hackish)是插入一个中间件,该中间件将在任何 MVC 代码之前执行。该中间件将为用户添加通用的经过身份验证的身份(如果用户还没有)。
因此,AuthorizeFilter检查将通过,方法Handle上的方法AuthenticationHandler将被执行,我们的问题将得到解决。Configure中间件代码(调用前需要添加app.UseMvc();)如下
app.Use(async (context, next) =>
{
if (!context.User.Identities.Any(i => i.IsAuthenticated))
{
context.User = new ClaimsPrincipal(new GenericIdentity("Unknown"));
}
await next.Invoke();
});
Run Code Online (Sandbox Code Playgroud)
AuthorizeFilter此处概述了覆盖的另一种方法( Override global Authorize Filter in ASP.NET Core MVC 1.0)
引用此处的响应(基于 Asp.Net Core 策略的授权以 401 Unauthorized 结尾)