由于 cors 问题无法使 Signal R 工作 - 被 cors 策略阻止
Cannot get Signal R working due to cors issue - blocked by cors policy
我正在使用 React 和 Signal R
我有一个托管我的集线器的标准 Web 应用程序。
当我发送消息时,在 Web 应用程序的网页中一切正常
我还有一个托管在端口 3000 上的 React 应用程序
我按照以下更改了 IIS Express 设置
<httpProtocol>
<customHeaders>
<clear />
<add name="X-Powered-By" value="ASP.NET" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
我的 cors 等服务器端启动如下
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddCors(options =>
{
options.AddPolicy("cors",
builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("http://localhost:3000");
});
});
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors("cors");
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chatHub");
endpoints.MapRazorPages();
});
}
在 React 端我实现如下
import React, { Component } from 'react';
import * as signalR from '@aspnet/signalr';
class Chat extends Component {
constructor(props) {
super(props);
this.state = {
nick: '',
message: '',
messages: [],
hubConnection: null,
};
}
componentDidMount = () => {
const protocol = new signalR.JsonHubProtocol();
const transport = signalR.HttpTransportType.WebSockets;
const options = {
transport,
logMessageContent: true,
logger: signalR.LogLevel.Trace,
};
// create the connection instance
var hubConnection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:44360/chatHub", options)
.withHubProtocol(protocol)
.build();
this.setState({ hubConnection }, () => {
this.state.hubConnection
.start()
.then(() => console.log('Connection started!'))
.catch(err => console.log('Error while establishing connection :('));
this.state.hubConnection.on('SendMessage', (user, message) => {
const text = `${user}: ${message}`;
const messages = this.state.messages.concat([text]);
console.log('ssss');
this.setState({ messages });
});
});
}
render() {
return (
<div>
<br />
<div>
{this.state.messages.map((message, index) => (
<span style={{display: 'block'}} key={index}> {message} </span>
))}
</div>
</div>
);
}
}
export default Chat;
如您所见,我已连接到我的服务器应用程序所在的确切端口
我在日志中收到一个条目,表明我已连接
但是,我实际上从未收到任何消息?
我在网络应用程序中的中心如下所示
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//Disable send button until connection is established
document.getElementById("sendButton").disabled = true;
connection.on("ReceiveMessage", function (user, message) {
var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});
connection.start().then(function () {
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});
document.getElementById("sendButton").addEventListener("click", function (event) {
var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
我以为我已经解决了 Cors 问题,但是当我让网页打开一段时间后,我收到了错误
Access to XMLHttpRequest at 'http://localhost:44360/chatHub/negotiate' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
谁能看出我做错了什么?
尝试像这样设置 Cors:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder.WithOrigins("http://localhost:3000")
.SetIsOriginAllowed((host) => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
经过几个小时的尝试,我终于让它工作了
我将把这个问题连同我的解决方案一起保留在这里以帮助其他人
首先 - 在 ConfigureServices 中:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddCors();
services.AddSignalR();
}
确保 Cors 在信号 R 之前
然后在配置
// Make sure the CORS middleware is ahead of SignalR.
app.UseCors(builder =>
{
builder.WithOrigins("http://localhost:3000") //Source
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MYHubClass>("/myHub");
});
确保 UseCors 在 UseEndpoints 之前
问题是您在 IIS 配置和代码中都定义了来源。如果 (1) 您只信任服务器上所有应用程序的单一来源,或 (2) 您信任服务器上所有应用程序的所有来源,您应该只在 IIS 配置中指定来源。
在服务器级别的配置中指定时,管道中的每个 http 上下文都添加了 Access-Control-Allow-Origin header。然后,WithOrigins(<origin>)
方法向其附加另一个值。
6.4 Implementation Considerations This section is non-normative.
Resources that wish to enable themselves to be shared with multiple
Origins but do not respond uniformly with "*" must in practice
generate the Access-Control-Allow-Origin header dynamically in
response to every request they wish to allow. As a consequence,
authors of such resources should send a Vary: Origin HTTP header or
provide other appropriate control directives to prevent caching of
such responses, which may be inaccurate if re-used across-origins.
尝试在 Azure Web 应用程序的 CORS 设置中启用 Access-Control-Allow-Credentials。
I included a screenshot
我正在使用 React 和 Signal R
我有一个托管我的集线器的标准 Web 应用程序。
当我发送消息时,在 Web 应用程序的网页中一切正常
我还有一个托管在端口 3000 上的 React 应用程序
我按照以下更改了 IIS Express 设置
<httpProtocol>
<customHeaders>
<clear />
<add name="X-Powered-By" value="ASP.NET" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
我的 cors 等服务器端启动如下
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddCors(options =>
{
options.AddPolicy("cors",
builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("http://localhost:3000");
});
});
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors("cors");
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chatHub");
endpoints.MapRazorPages();
});
}
在 React 端我实现如下
import React, { Component } from 'react';
import * as signalR from '@aspnet/signalr';
class Chat extends Component {
constructor(props) {
super(props);
this.state = {
nick: '',
message: '',
messages: [],
hubConnection: null,
};
}
componentDidMount = () => {
const protocol = new signalR.JsonHubProtocol();
const transport = signalR.HttpTransportType.WebSockets;
const options = {
transport,
logMessageContent: true,
logger: signalR.LogLevel.Trace,
};
// create the connection instance
var hubConnection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:44360/chatHub", options)
.withHubProtocol(protocol)
.build();
this.setState({ hubConnection }, () => {
this.state.hubConnection
.start()
.then(() => console.log('Connection started!'))
.catch(err => console.log('Error while establishing connection :('));
this.state.hubConnection.on('SendMessage', (user, message) => {
const text = `${user}: ${message}`;
const messages = this.state.messages.concat([text]);
console.log('ssss');
this.setState({ messages });
});
});
}
render() {
return (
<div>
<br />
<div>
{this.state.messages.map((message, index) => (
<span style={{display: 'block'}} key={index}> {message} </span>
))}
</div>
</div>
);
}
}
export default Chat;
如您所见,我已连接到我的服务器应用程序所在的确切端口
我在日志中收到一个条目,表明我已连接
但是,我实际上从未收到任何消息?
我在网络应用程序中的中心如下所示
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//Disable send button until connection is established
document.getElementById("sendButton").disabled = true;
connection.on("ReceiveMessage", function (user, message) {
var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});
connection.start().then(function () {
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});
document.getElementById("sendButton").addEventListener("click", function (event) {
var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
我以为我已经解决了 Cors 问题,但是当我让网页打开一段时间后,我收到了错误
Access to XMLHttpRequest at 'http://localhost:44360/chatHub/negotiate' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
谁能看出我做错了什么?
尝试像这样设置 Cors:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder.WithOrigins("http://localhost:3000")
.SetIsOriginAllowed((host) => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
经过几个小时的尝试,我终于让它工作了
我将把这个问题连同我的解决方案一起保留在这里以帮助其他人
首先 - 在 ConfigureServices 中:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddCors();
services.AddSignalR();
}
确保 Cors 在信号 R 之前
然后在配置
// Make sure the CORS middleware is ahead of SignalR.
app.UseCors(builder =>
{
builder.WithOrigins("http://localhost:3000") //Source
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MYHubClass>("/myHub");
});
确保 UseCors 在 UseEndpoints 之前
问题是您在 IIS 配置和代码中都定义了来源。如果 (1) 您只信任服务器上所有应用程序的单一来源,或 (2) 您信任服务器上所有应用程序的所有来源,您应该只在 IIS 配置中指定来源。
在服务器级别的配置中指定时,管道中的每个 http 上下文都添加了 Access-Control-Allow-Origin header。然后,WithOrigins(<origin>)
方法向其附加另一个值。
6.4 Implementation Considerations This section is non-normative.
Resources that wish to enable themselves to be shared with multiple Origins but do not respond uniformly with "*" must in practice generate the Access-Control-Allow-Origin header dynamically in response to every request they wish to allow. As a consequence, authors of such resources should send a Vary: Origin HTTP header or provide other appropriate control directives to prevent caching of such responses, which may be inaccurate if re-used across-origins.
尝试在 Azure Web 应用程序的 CORS 设置中启用 Access-Control-Allow-Credentials。 I included a screenshot