由于存在cors问题,Signal R无法正常工作-被cors政策禁止

时间:2019-10-22 18:41:42

标签: reactjs cors signalr cors-anywhere

我正在使用带有信号R的React

我有一个托管我的中心的标准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;

如您所见,我已连接到服务器应用程序所在的确切端口

我在日志中得到一个条目说我已连接

但是,我实际上从未收到任何消息吗?

我在Web应用程序中的中心显示如下

"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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    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.

有人能看到我做错了吗?

3 个答案:

答案 0 :(得分:1)

问题在于您已经在IIS配置和代码中定义了源。仅应在以下情况下在IIS配置中指定来源:(1)您仅信任服务器上所有应用程序的单个来源,或者(2)您信任服务器上所有应用程序的所有来源。

在服务器级别的配置中指定时,管道中的每个http上下文都添加了Access-Control-Allow-Origin标头。然后,WithOrigins(<origin>)方法向其附加另一个值。

https://www.w3.org/TR/cors/

  

6.4实现注意事项本节是非规范性的。

     

希望与多个资源共享的资源   在实践中必须使用起源,但不能统一用“ *”表示   动态生成Access-Control-Allow-Origin标头   回应他们希望允许的每个请求。作为结果,   这些资源的作者应发送Vary:Origin HTTP标头或   提供其他适当的控制指令以防止缓存   这样的响应,如果跨地区重复使用,可能会不准确。

答案 1 :(得分:0)

尝试这样设置Cors:

   Sub age()
      Dim OpenWb As Workbook
      With Application.FileDialog(msoFileDialogFilePicker)
            'Makes sure the user can select only one file
            .AllowMultiSelect = False
            'Filter to just the following types of files to narrow down selection options
            .Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
            'Show the dialog box
            .Show

            'Store in fullpath variable
            fullpath = .SelectedItems.Item(1)

            'Actions in raw data sheet

        Set OpenWb = Workbooks.Open(fullpath)
        Dim wsData As Worksheet
        Set wsData = OpenWb.Worksheets("Data")

     'Find last cell number of row A from data sheet
        Dim last As Double
        Dim Cell As Range
        With OpenWb.Worksheets("Data")
        last = .Cells(.Rows.Count, "A").End(xlUp).Row
        End With

    OpenWb.Worksheets("Data").Rows("1:1").Select
    Dim f1 As String

    f1 = Selection.Find(What:="BIRTH_YEAR", After:=ActiveCell, LookIn:=xlValues, _
            LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
            MatchCase:=False, SearchFormat:=False).value

        Selection.AutoFilter
        ActiveWorkbook.Worksheets("Data").AutoFilter.Sort.SortFields.Clear
    '    Cells(f1).Sort , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
    '        xlSortTextAsNumbers
''Macro recording-Iwant to replace the range C1:C499872 with f1(variabe)        
ActiveWorkbook.Worksheets("Data").AutoFilter.Sort.SortFields.Add2 Key:=Range( _
            "C1:C499872"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
            xlSortTextAsNumbers
        With ActiveWorkbook.Worksheets("Data").AutoFilter.Sort
            .Header = xlYes
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With
    End With



    End Sub

答案 2 :(得分:0)

经过数小时的尝试,我终于使它工作了

我将在此处保留此问题以及我的解决方案以帮助他人

首先-在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之前