在一个项目中,我有一个可以进行授权的 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();
}