.NET Core 2.1 - 未达到 AuthorizationHandler 且始终 return 401

.NET Core 2.1 - AuthorizationHandler not reached and always return 401

我已经实现了自定义授权处理程序来确定用户是否有权编辑或删除资源。
但是处理程序从未被调用,当我尝试编辑资源时,我总是得到 401 状态代码。

这是我的自定义处理程序:

public class MeetingAuthorizationHandler : AuthorizationHandler<SameCreatorRequirement, Meeting>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SameCreatorRequirement requirement, Meeting resource)
    {
        /*if (context.User.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).FirstOrDefault() != null)
        {
            int idCreator = Int32.Parse(context.User.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).FirstOrDefault().Value);
            if(idCreator == resource.CreatedBy.IdUserPreferences)
            {
                context.Succeed(requirement);
            }
        }*/

        context.Succeed(requirement);

        return Task.CompletedTask;
    }
}

public class SameCreatorRequirement : IAuthorizationRequirement
{
}

我还在配置方法中添加了这些行:

services.AddSingleton<IAuthorizationHandler, MeetingAuthorizationHandler>();
services.AddAuthorization(options =>
{
    options.AddPolicy("Admin", policy => policy.RequireClaim("Admin"));
    options.AddPolicy("EditPolicy", policy => policy.Requirements.Add(new SameCreatorRequirement()));
});

在控制器中,我使用这个:

[Route("Meetings/Edit/{id}")]
[Authorize(Policy = "EditPolicy")]
public async Task<IActionResult> Edit(int id)

我已经阅读了很多相关的文章 post,我可以找到它不起作用的原因。这段代码有什么问题?

编辑 1

我在输出中找到了这个(我使用没有身份的 Cookie 身份验证,请参阅 this

    Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization was successful.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ForbidResult:Information: Executing ForbidResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was forbidden.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action RoomScheduling.Controllers.MeetingsController.Edit (RoomScheduling) in 21.4851ms

编辑 2

这是我的控制器:

namespace RoomScheduling.Controllers
{
    [Authorize]
    public class MeetingsController : Controller
    {

       /** ------------------- **/

        [Route("Meetings/Edit/{id}")]
        [Authorize(Policy = "EditPolicy")]
        public async Task<IActionResult> Edit(int id)
        {
            MeetingView meetingView = new MeetingView();

            Meeting meeting = await _context.Meeting
                .Include(m => m.Room)
                .Include(m => m.MeetingType)
                .Include(m => m.CreatedBy)
                //.Include(m => m.UpdatedBy)
                .Include(m => m.Attendees)
                .AsNoTracking()
                .SingleAsync(m => m.IdMeeting == id);

            meeting.UpdatedBy = new UserPreferences();
            meeting.UpdatedBy.IdUserPreferences = GetCurrentUserId();
            meetingView.Meeting = meeting;
            meetingView.Attendees = meeting.Attendees.Select(c => c.Attendant).ToArray();

            ViewBag.RoomId = new SelectList(_context.Room.AsNoTracking().Include(m => m.Area).ToList(), "IdRoom", "Name", meeting.Room.IdRoom, "Area.Name"); //Dropdown list
            ViewBag.MeetingTypeId = new SelectList(_context.MeetingType.AsNoTracking().ToList(), "IdMeetingType", "Name"); //Dropdown list
            ViewBag.AttendeesIdList = new MultiSelectList(_context.Attendees.AsNoTracking().Select(a => a.Attendant).Distinct().ToList(), "", "", meetingView.Attendees);

            return View(meetingView);
        }

       /** ------------------- **/
    }
}

问题是您正在尝试对资源进行授权。您的策略不知道如何检索或访问 Meeting 资源。

如果你想在你的 AuthorizationHandler 中做出需要访问 Meeting 对象的决定,你可以将 IAuthorizationService 注入你的控制器并使用你的 Meeting资源。

[Route("Meetings/Edit/{id}")]
[Authorize(Policy = "EditPolicy")]
public async Task<IActionResult> Edit(int id)
{
    MeetingView meetingView = new MeetingView();

    Meeting meeting = await _context.Meeting
        .Include(m => m.Room)
        .Include(m => m.MeetingType)
        .Include(m => m.CreatedBy)
        //.Include(m => m.UpdatedBy)
        .Include(m => m.Attendees)
        .AsNoTracking()
        .SingleAsync(m => m.IdMeeting == id);

    // Authorize the user against the EditPolicy using the meeting resource.
    var result = await _authorizationService.AuthorizeAsync(User, meeting, "EditPolicy");
    if (!result.Succeeded)
    {
        return Forbid();
    }
    // Do stuff.
}

如果您不想对资源做出授权决定,您可以使用不同的 AuthorizationHandler<TRequirement> 例如:

public class MeetingAuthorizationHandler : AuthorizationHandler<SameCreatorRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SameCreatorRequirement requirement)
    {
        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}