Не удается заставить работать Signal R из-за проблемы cors - заблокировано политикой cors - PullRequest
0 голосов
/ 22 октября 2019

Я использую React с сигналом R

У меня есть стандартное веб-приложение, в котором размещается мой хаб.

Когда я отправляю сообщения, все отлично работает на веб-странице для веб-приложения

У меня также есть приложение реагирования, которое размещено на порту 3000

. Я изменил настройки 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, "&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();
});

Iдумал, что я решил проблемы с 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 ]

1 голос
/ 26 октября 2019

Проблема в том, что вы определили источники как в конфигурации IIS, так и в коде. Вы должны указывать источники только в конфигурации IIS, если (1) вы доверяете только одному источнику для всех приложений на сервере или (2) доверяете всем источникам для всех приложений на сервере.

Если указано вconfig на уровне сервера, каждый HTTP-контекст в конвейере имеет добавленный заголовок Access-Control-Allow-Origin. Затем метод WithOrigins(<origin>) добавляет к нему другое значение.

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

6.4 Соображения по поводу реализации Этот раздел является ненормативным.

Ресурсы, которые желаютчтобы позволить им совместно использовать несколько источников, но не отвечать единообразно с помощью «*», на практике необходимо динамически генерировать заголовок Access-Control-Allow-Origin в ответ на каждый запрос, который они хотят разрешить. Как следствие, авторы таких ресурсов должны отправлять HTTP-заголовок Vary: Origin или предоставлять другие соответствующие директивы управления для предотвращения кэширования таких ответов, которые могут быть неточными, если их повторно использовать в разных источниках.

0 голосов
/ 25 октября 2019

После нескольких часов попыток я, наконец, заставил это работать

Я собираюсь оставить этот вопрос здесь вместе со своим решением, чтобы помочь другим

Сначала - в ConfigureServices:

  public void ConfigureServices(IServiceCollection services)
  {
    services.AddRazorPages();
    services.AddCors();
    services.AddSignalR();
  }

Обеспечение Cors перед сигналом R

Затем в Configure

        // 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

0 голосов
/ 23 октября 2019

Попробуйте установить Cors следующим образом:

services.AddCors(options =>
{
    options.AddPolicy("CorsPolicy", builder => builder.WithOrigins("http://localhost:3000")
        .SetIsOriginAllowed((host) => true)
        .AllowAnyMethod()
        .AllowAnyHeader()
        .AllowCredentials());
});
...