SignalR集线器授权属性不起作用 [英] SignalR hub Authorize attribute doesn't work
问题描述
我正在使用SignalR将通知发送到angular.但我想使其针对特定用户.用户使用天蓝色广告登录.我在集线器上有一个[授权],但是授权失败.但是在我的控制器中,它可以正常工作.
I'm using SignalR to send notification to angular. But i want to make it user specific. The user is logged in with azure ad. And i have a [Authorize] on the hub but the authorisation fails. But in my controller it works fine.
到目前为止我尝试过的.我尝试了来自Microsoft网站的services.AddAuthentication. https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2 但是然后我的控制器无法验证令牌,因为令牌不在URL中,而在标头中.
What i have tried so far. I tried this services.AddAuthentication from the microsoft site. https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2 But then my controller can't verify the token because the token isn't in the url but in the header.
startup.cs:
startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
// Add custom configuration/resource files
services.ConfigureSettings(Configuration);
services.Configure<GzipCompressionProviderOptions>(options =>
options.Level = System.IO.Compression.CompressionLevel.Fastest
);
services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<GzipCompressionProvider>();
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.WithOrigins("http://localhost:4200"));
});
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAD", options));
services.AddSignalR();
// Add framework services.
services.AddMvc(options =>
{
options.Filters.Add(new ValidateModelStateFilter());
}).AddJsonOptions(options =>
{
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
});
我的中心:
[Authorize]
public class NotifyHub : Hub<ITypedHubClient>
{
public Task SendMessage(string user, string message)
{
return Clients.Client(Context.ConnectionId)
.BroadcastMessage("ReceiveMessage", user, message);
}
public Task Log(string email)
{
Debug.WriteLine(Context.ConnectionId);
return Clients.Caller.BroadcastMessage("succes", "string");
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
}
Angular SignalR服务:
angular SignalR service:
private createConnection() {
this._hubConnection = new HubConnectionBuilder()
.withUrl('https://localhost:44334/notify', { accessTokenFactory: () => {
return this.adalSvc.accessToken } })
.build();
}
我想让用户进入我的中心,这样我就可以将用户映射到连接ID.
I want to get the user in my hub so i can map the users to the connection id's.
推荐答案
SignalR的问题在于它无法修改标头来发送令牌,
The problem with SignalR is that it cannot modify the header to send the token so
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAD", options));
不适用于SignalR,因为URL中应包含令牌.
does not work with SignalR as the token is expected in the URL.
以下内容可用于Authenticated API调用和Authenticated SignalR连接
The following however works with both Authenticated API calls and Authenticated SignalR connections
services.AddAuthentication(options = >{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options = >{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.Authority = "https://login.microsoftonline.com/" + Configuration["AzureAd:TenantId"];
options.TokenValidationParameters = new TokenValidationParameters() {
// These need to be set correctly after checking that it works
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = false,
ValidateActor = false
};
options.Events = new JwtBearerEvents {
OnMessageReceived = ctx = >{
if (ctx.Request.Query.ContainsKey("access_token"))
ctx.Token = ctx.Request.Query["access_token"];
return Task.CompletedTask;
}
};
});
您可以在集线器中对此进行测试
You can test this in your hub
public override async Task OnConnectedAsync()
{
var Oid = (Context.User.FindFirst(c =>
c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
Debug.WriteLine(Oid);
}
API和SignalR的[Authorize]属性都来自
Both [Authorize] attributes for API and SignalR come from
using Microsoft.AspNetCore.Authorization;
这篇关于SignalR集线器授权属性不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!