【问题标题】:Inform the user of unauthorized method call通知用户未经授权的方法调用
【发布时间】:2023-02-02 11:10:21
【问题描述】:

我目前正在使用 SignalR Core 开发 Web 应用程序。我正在使用 AuthorizeAttribute(无角色)来确保只有经过身份验证的用户才能连接到我们的集线器。 对于某些方法,需要特定的策略。这些方法还使用包含特定策略的 AuthorizeAttribute 进行修饰。这是我的集线器代码:

[Authorize]
public class CustomerHub : Hub
{
    public async Task SimpleMethod()
    {
        // Do things that don't require additional authorization
        await Task.CompletedTask;
    }

    [Authorize(Policies.IsAdmin)]
    public async Task AdvancedMethod()
    {
        // Do things that require admin authorization
        await Task.CompletedTask;
    }
    
    public async Task ErrorMethod()
    {
        await Task.CompletedTask;
        throw new NotImplementedException();
    }
}

一切都按预期工作。我能够连接到集线器并调用 SimpleMethod,并且当我在没有足够权限的情况下调用它时,调试器不会进入 AdvancedMethod。但是,当用户无权调用特定方法时,我想通知他们。但在这种情况下,不会将特定错误或消息发送回客户端。我确实实现了一个自定义 IHubFilter,它会通知用户错误,但结果是在调用此 HubFilter 之前评估了 AuthorizeAttribute。

    public class CustomHubExceptionsFilter : IHubFilter
    {
        public async ValueTask<object?> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object?>> next)
        {
            try
            {
                var result = await next(invocationContext);
                return result;
            }
            catch (Exception ex)
            {
                await invocationContext.Hub.Clients.Caller.SendCoreAsync("Error", new object?[] { $"Oops, something went wrong. Technical details: {ex.GetType().Name}" });

                throw;
            }
        }
    }

我还尝试添加一个自定义 AuthorizationHandler,当用户未经授权时返回错误。但是,这会导致连接关闭,我认为这不是一个很好的解决方案。

是否可以使用 AuthorizeAttributes 通知用户?我可以创建一个自定义 IHubFilter 来检查用户是否获得授权。但这需要大量自定义代码。是否有更简单/更原生的方法可用?

【问题讨论】:

    标签: asp.net authorization signalr asp.net-core-signalr


    【解决方案1】:

    我建议你可以考虑在自定义的AuthorizationHandler里面直接调用Hub方法的ErrorMethod直接返回异常。

    例如:

    我们需要将连接 ID 存储在请求中,然后在 AuthorizationHandler 中我们可以获取它,然后使用 hub 方法将错误返回给客户端。

    像这样 :

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ConnectionRequirement requirement)
    {
        var connectionIdClaim = context.User.FindFirst("connectionId");
        if (connectionIdClaim == null)
        {
            context.Fail();
            return;
        }
    
        var connectionId = connectionIdClaim.Value;
    
        await _hubContext.Clients.Client(connectionId).SendAsync("message", "You are not authorized to perform this action.");
    
        context.Fail();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-20
      • 1970-01-01
      • 2014-07-18
      • 2021-04-15
      • 2013-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多