JWTBearerToken授权在我的Signalr应用程序中不起作用。
作为服务器,我使用Asp.net core 2.2 WebAPI,作为客户端,我创建了WPF应用程序。
在客户端应用程序启动时,登录方法将称为:
private async void Login()
{
var httpContent = new StringContent(JsonConvert.SerializeObject(currentUser), Encoding.UTF8, "application/json");
var response = await new HttpClient().PostAsync("https://localhost:5001/api/auth/user", httpContent);
if (response.IsSuccessStatusCode)
{
currentUser = JsonConvert.DeserializeObject<User>(await response.Content.ReadAsStringAsync());
connection = new HubConnectionBuilder()
.WithUrl("https://localhost:5001/notify", options =>
{
options.AccessTokenProvider = () => Task.FromResult(currentUser.Token);
})
.Build();
}
}
用户类如下:
public class User
{
public string Username { get; set; }
public string Password { get; set; }
public string Token { get; set; }
}
因此,在我的情况下,响应对象包含服务器分配的令牌。
如果我现在单击“连接”按钮,则将调用以下方法:
private async void connectButton_Click(object sender, RoutedEventArgs e)
{
#region snippet_ConnectionOn
connection.On<string, string>("BroadcastMessage", (id, message) =>
{
this.Dispatcher.Invoke(() =>
{
var newMessage = $"{id}: {message}";
messagesList.Items.Add(newMessage);
});
});
#endregion
try
{
await connection.StartAsync();
messagesList.Items.Add("Connection started");
connectButton.IsEnabled = false;
sendButton.IsEnabled = true;
}
catch (Exception ex)
{
messagesList.Items.Add(ex.Message);
}
}
服务器对连接的响应。StartAsync()方法导致“未经授权”异常。
这是我的服务器启动类的样子:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISitesRepository, SitesRepository>();
services.AddSingleton<INotificationManager, NotificationManager>();
services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
services.AddSignalR();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
var authSettingsSection = Configuration.GetSection("AuthSettings");
services.Configure<AuthSettings>(authSettingsSection);
var authSettings = authSettingsSection.Get<AuthSettings>();
var key = Encoding.ASCII.GetBytes(authSettings.Secret);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
//x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters =
new TokenValidationParameters
{
LifetimeValidator = (before, expires, token, param) =>
{
return expires > DateTime.UtcNow;
},
ValidateAudience = false,
ValidateIssuer = false,
ValidateActor = false,
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(key)
};
x.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
if (string.IsNullOrEmpty(accessToken) == false)
{
context.Token = accessToken;
}
var found = context.Request.Headers["Authorization"];
if (found != default(Microsoft.Extensions.Primitives.StringValues))
{
var foundToken = found.FirstOrDefault(h => h.StartsWith("Bearer"));
context.Token = foundToken.Replace("Bearer ", "");
}
return Task.CompletedTask;
}
};
});
services.AddScoped<IAuthService, AuthService>();
}
context.Request.Query [“ access_token”] 始终返回空值。
这是集线器的测试代码:
[Authorize]
public class NotifyHub: Hub, INotifyHub
{
public NotifyHub() { }
//public override async Task OnConnectedAsync()
//{
// await Groups.AddToGroupAsync(Context.ConnectionId, "Devices");
// await base.OnConnectedAsync();
//}
//public override async Task OnDisconnectedAsync(Exception exception)
//{
// await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Devices");
// await base.OnDisconnectedAsync(exception);
//}
public async Task ReceivedBroadcastMessage(string id, string message)
{
await Task.Run(() =>
{
if (id == "a")
{
SendBroadcastMessage("b", "c");
}
});
}
public async Task SendBroadcastMessage(string id, string message)
{
await Clients.All.SendAsync("BroadcastMessage", id, message);
}
}
有什么想法吗?