1

在一个项目中,我有一个可以进行授权的 SignalR 集线器。集线器的简化版本如下所示。

public class WeatherHub : Hub
{
    public async Task SubscribeForWeatherChange(string city)
    {
        // Will never throw. Based on authentication state it will evaluate to true or false regardless of Azure
        // SignalR service is being used or not.
        bool authenticated1 = this.Context.User.Identity.IsAuthenticated;
        bool authenticated2 = this.Context.GetHttpContext().User.Identity.IsAuthenticated;

        // Will throw when Azure SignalR service is being used.
        string accessToken = await this.Context.GetHttpContext().GetTokenAsync("cookies", "access_token");
        this.EnsureIsAuthorized(accessToken);  // Executes HTTP call and throws based on response (!= 200).

        await this.Groups.AddToGroupAsync(this.Context.ConnectionId, city);
    }

    public async Task SendWeatherChange(string city, string weather)
    {
        await this.Clients.Group(city).SendAsync("WeatherChanged", city, weather);
    }
}

这段代码运行得很好。正在提取访问令牌,可在执行 HTTP 调用时使用。当我们想要使用 Azure SignalR 服务时,就会出现问题。在这种情况下,读取访问令牌不起作用。

我的调查表明,当使用 SignalR 服务时,扩展方法GetTokenAsync(this HttpContext context, string scheme, string tokenName)会抛出 ArgumentNullException,因为它context.RequestServices是 null。

我的授权方式错了吗?有更好的方法吗?为什么 IServiceProvider 为空?

我的服务配置如下所示。

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddSignalR()
        .AddAzureSignalR();

    services
        .AddAuthentication(options =>
        {
            options.DefaultScheme = "cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("cookies", options =>
        {
            // cookie configuration
        })
        .AddOpenIdConnect("oidc", options =>
        {
            options.SaveTokens = true;
            // oidc configuration
        });

    services.AddControllers();
}
4

0 回答 0