403 (Запрещено) ответ от SignalR Hub с использованием ASP.NET хостинга на сервере IIS - PullRequest
0 голосов
/ 09 октября 2018

Я размещаю SignalR Hub на Windows Server 2012 с IIS в качестве веб-приложения ASP.NET, которое я успешно протестировал на своем локальном компьютере.Но когда я публикую и пытаюсь подключиться из приложения Angular, сервер отвечает 403 Forbidden на запрос /gotiate.Приложение Angular расположено в другом домене, чем сервер-концентратор.

Я читал, что это вызвано проблемой CORS, но я пробовал каждое найденное решение без каких-либо изменений.Это может быть проблема с сервером IIS или я что-то пропустил в своем коде?

Вызываемый маршрут: https://example.com/signalr/negotiate

Сервер SignalR:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Map("/signalr", map =>
        {
            map.UseCors(CorsOptions.AllowAll);

            var hubConfiguration = new HubConfiguration
            {
                EnableJSONP = true,
                EnableDetailedErrors = true
            };

            map.RunSignalR(hubConfiguration);
        });
    }
}

// Hub that handles Online user list
public class OnlineHub : Hub
{
    private static List<AppUserDto> _usersOnline = new List<AppUserDto>();

    public OnlineHub()
    {
        // Automapper Setup
        MappingConfig.Init();
    }

    public override Task OnConnected()
    {
        var user = GetUser();
        _usersOnline.Add(user);
        Clients.All.listUpdated(_usersOnline);

        return base.OnConnected();
    }

    public override Task OnReconnected()
    {
        var user = GetUser();

        // Add user to list of online users if it doesn't exist
        if (!_usersOnline.Any(u => u.Email == user.Email))
        {
            _usersOnline.Add(user);
            Clients.All.listUpdated(_usersOnline);
        }

        return base.OnReconnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        var user = GetUser();
        if (!_usersOnline.Any(u => u.Email == user.Email))
        {
            // Remove user from list of online users
            _usersOnline.Remove(user);

            Clients.All.listUpdated(_usersOnline);
        }

        return base.OnDisconnected(stopCalled);
    }

    private AppUserDto GetUser()
    {
        using (var db = new EntityDbContext())
        {
            // Get connected AppUserDto
            var user = db.AppUsers.FirstOrDefault(u => u.UserName == Context.User.Identity.Name);
            // Add user to list of online users
            if (user != null)
            {
                return Mapper.Map<AppUserDto>(user);
            }

            return null;
        }
    }
}

Служба Angular Application SignalR

import { AppSettings } from './../app.settings';
import { EventEmitter, Injectable } from '@angular/core';

declare const $: any;

@Injectable()
export class SignalRService {
  // Declare the variables
  private proxy: any;
  private connection: any;
  private authData: any;
  // create the Event Emitter
  public messageReceived: EventEmitter<any>;
  public connectionEstablished: EventEmitter<Boolean>;
  public connectionExists: Boolean;

  constructor(private appSettings: AppSettings) {
    // Setup
    this.connectionEstablished = new EventEmitter<Boolean>();
    this.messageReceived = new EventEmitter<any>();
    this.connectionExists = false;
  }

  public initialize(proxyName: string): void {
    this.connection = $.hubConnection(this.appSettings.SIGNALR_BASE_URL);
    this.proxy = this.connection.createHubProxy(proxyName);
    this.registerOnServerEvents();
    this.startConnection();
  }

  private startConnection(): void {
    this.connection.start({withCredentials: false})
      .done((data: any) => {
        console.log('SignalR Connected with: ' + data.transport.name);
        this.connectionEstablished.emit(true);
        this.connectionExists = true;
      })
      .fail((error: any) => {
        console.log('SignalR could not connect: ' + error);
        this.connectionEstablished.emit(false);
      });
  }

  private registerOnServerEvents() {
    this.proxy.on('listUpdated', (list: any) => {
      console.log(list);
      this.messageReceived.emit(list);
    });
  }
}

initialize (proxyName) вызывается из контроллера для установления соединения с концентратором.

UPDATE

Я пытался восстановить сервер и концентратор с помощью .NET Core 2.0, но при тестировании этого на сервере IIS получаю:

"Не удалось загрузитьhttps://signalr.example.com/online/negotiate: Ответ на предварительный запрос не проходит проверку контроля доступа: на запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Следовательно, Origin 'https://example.com' не имеет доступа."

Так что это все еще проблема CORS, хотя я настроил все так же, как несколько руководств.

1 Ответ

0 голосов
/ 09 октября 2018

В прошлом у меня были проблемы, когда путь API, по которому вы пытаетесь перейти, фактически является виртуальным каталогом, а затем IIS возвращает вам 403, потому что он думает, что вы пытаетесь просмотреть / получить доступ к этому каталогу вместомаршрут webAPI.

GET api/negotiate будет 403, если на вашем сервере есть каталог api/negotiate.

Это будет иметь место, если ваш WebApiController находится в вашем проекте в каталоге, подобном:

/api/negotiate/NegotiateApiController.cs

Вы можете решить эту проблему очень легко, если это так, изменив маршрут или имя каталога.

Примечание. В некоторых случаях это возвращается как 405браузеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...