Angular 连接到 ASP.NET API SignalR Hub return 404 未找到(Identity Server 3)
Angular connect to ASP.NET API SignalR Hub return 404 Not Found (Identity Server 3)
我在 Angular 8 和 ASP.NET Web API 之间进行 SignalR 通信,.NET Framework 4.7.2 工作正常。但是我已经几个月没有测试过了,现在当我尝试时,我在浏览器控制台中得到了结果:
http://localhost:55454/signalr/negotiate? .... net::ERR_ABORTED 404(未找到)
这几个月唯一的主要变化是现在我的 API 使用 Identity Server 3,但我不认为这是问题所在。
然而,这是我在 Identity Server 实施之前在 StartUp 中的代码:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true,
};
map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new QueryStringOAuthBearerProvider(),
AccessTokenProvider = new AuthenticationTokenProvider()
{
OnCreate = new Action<AuthenticationTokenCreateContext>(c =>
{
c.SetToken(c.SerializeTicket());
}),
OnReceive = new Action<AuthenticationTokenReceiveContext>(c =>
{
c.DeserializeTicket(c.Token);
c.OwinContext.Environment["Properties"] = c.Ticket.Properties;
})
},
});
map.RunSignalR(hubConfiguration);
});
和 QueryStringOAuthBearerProvider(因为我在查询字符串中发送了令牌):
private class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
public override Task RequestToken(OAuthRequestTokenContext context)
{
if (context != null)
{
var value = context.Request.Query.Get("token");
if (!string.IsNullOrEmpty(value))
{
context.Token = value;
}
}
return Task.FromResult<object>(null);
}
}
我尝试了新的一段代码,但结果还是一样:
app.UseIdentityServerBearerTokenAuthentication(new
IdentityServerBearerTokenAuthenticationOptions
{
Authority = identityAuthority,
});
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true,
};
map.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions
{
Authority = identityAuthority,
TokenProvider = new QueryStringOAuthBearerProvider(),
});
map.RunSignalR(hubConfiguration);
});
}
我认为这不是主要问题,因为在 Debug 中它永远不会遇到 QueryStringOAuthBearerProvider class 中的断点。它必须是。
我的 SignalR 版本在 API 中是 2.4.1,所以它在 Angular 中是 ("signalr": "^2.4.1",)
我也使用 "ng2-signalr": "^8.0.2" nuget 来保存一些手动编写的 JS 代码。
这是 Typescript 中的一个示例(以前可以使用):
startConnection(hubConnection: SignalR): Promise<ISignalRConnection> {
console.log('Connecting...');
if (this.authService && this.authService.token) {
return hubConnection.connect({ jsonp: true, hubName: 'ChatHub', url: this.config.API_BASE_URL, qs: { token: this.authService.token } });
}
}
可能是启动配置,但可能不是因为它看起来根本找不到这样的地址 (localhost/signalr...)
此 angular 项目的 CORS 策略已设置,所有其他常规 API 调用均正常工作。
我不明白为什么我会从不久前作为魅力发挥作用的某些功能中引发这个 404 错误。
编辑:
在数据库中,我保留了 Angular 应用程序的本地主机地址,并授予他完整的 CORS 访问权限,但这对 SignalR 来说足够了吗?是的,请求来自同一个本地主机,但没有调用 http://localhost:55454/api but http://localhost:55454/signalr,那么应该对 CORS 做一些额外的事情吗?我认为它可能应该,否则为什么要添加这行旧代码:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
有什么困难吗?
我已经解决了。最初的回应不是很详细。 404 就是这样。但是当我深入了解时,我发现详细的响应是:
HTTP 错误 404.15 - 未找到请求过滤模块配置为拒绝查询字符串太长的请求。
确实如此。所以现在我需要决定增加 URL 和查询字符串长度是否安全,如果不安全......如何解决这个问题。
我在 Angular 8 和 ASP.NET Web API 之间进行 SignalR 通信,.NET Framework 4.7.2 工作正常。但是我已经几个月没有测试过了,现在当我尝试时,我在浏览器控制台中得到了结果:
http://localhost:55454/signalr/negotiate? .... net::ERR_ABORTED 404(未找到)
这几个月唯一的主要变化是现在我的 API 使用 Identity Server 3,但我不认为这是问题所在。
然而,这是我在 Identity Server 实施之前在 StartUp 中的代码:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true,
};
map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new QueryStringOAuthBearerProvider(),
AccessTokenProvider = new AuthenticationTokenProvider()
{
OnCreate = new Action<AuthenticationTokenCreateContext>(c =>
{
c.SetToken(c.SerializeTicket());
}),
OnReceive = new Action<AuthenticationTokenReceiveContext>(c =>
{
c.DeserializeTicket(c.Token);
c.OwinContext.Environment["Properties"] = c.Ticket.Properties;
})
},
});
map.RunSignalR(hubConfiguration);
});
和 QueryStringOAuthBearerProvider(因为我在查询字符串中发送了令牌):
private class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
public override Task RequestToken(OAuthRequestTokenContext context)
{
if (context != null)
{
var value = context.Request.Query.Get("token");
if (!string.IsNullOrEmpty(value))
{
context.Token = value;
}
}
return Task.FromResult<object>(null);
}
}
我尝试了新的一段代码,但结果还是一样:
app.UseIdentityServerBearerTokenAuthentication(new
IdentityServerBearerTokenAuthenticationOptions
{
Authority = identityAuthority,
});
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true,
};
map.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions
{
Authority = identityAuthority,
TokenProvider = new QueryStringOAuthBearerProvider(),
});
map.RunSignalR(hubConfiguration);
});
}
我认为这不是主要问题,因为在 Debug 中它永远不会遇到 QueryStringOAuthBearerProvider class 中的断点。它必须是。
我的 SignalR 版本在 API 中是 2.4.1,所以它在 Angular 中是 ("signalr": "^2.4.1",) 我也使用 "ng2-signalr": "^8.0.2" nuget 来保存一些手动编写的 JS 代码。
这是 Typescript 中的一个示例(以前可以使用):
startConnection(hubConnection: SignalR): Promise<ISignalRConnection> {
console.log('Connecting...');
if (this.authService && this.authService.token) {
return hubConnection.connect({ jsonp: true, hubName: 'ChatHub', url: this.config.API_BASE_URL, qs: { token: this.authService.token } });
}
}
可能是启动配置,但可能不是因为它看起来根本找不到这样的地址 (localhost/signalr...) 此 angular 项目的 CORS 策略已设置,所有其他常规 API 调用均正常工作。
我不明白为什么我会从不久前作为魅力发挥作用的某些功能中引发这个 404 错误。
编辑:
在数据库中,我保留了 Angular 应用程序的本地主机地址,并授予他完整的 CORS 访问权限,但这对 SignalR 来说足够了吗?是的,请求来自同一个本地主机,但没有调用 http://localhost:55454/api but http://localhost:55454/signalr,那么应该对 CORS 做一些额外的事情吗?我认为它可能应该,否则为什么要添加这行旧代码:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
有什么困难吗?
我已经解决了。最初的回应不是很详细。 404 就是这样。但是当我深入了解时,我发现详细的响应是:
HTTP 错误 404.15 - 未找到请求过滤模块配置为拒绝查询字符串太长的请求。
确实如此。所以现在我需要决定增加 URL 和查询字符串长度是否安全,如果不安全......如何解决这个问题。