tutorial net mvc example signalr

net - Asegurando las llamadas de SignalR



signalr tutorial (4)

Estoy usando el cliente SignalR Javascript y ASP.NET ServiceHost. Necesito que los concentradores y las devoluciones de llamada de SignalR solo sean accesibles para los usuarios que han iniciado sesión. También necesito poder obtener la identidad del usuario que ha iniciado sesión actualmente en el concentrador mediante FormsIdentity de HttpContext.Current.User.

  1. ¿Cómo aseguro los concentradores para que solo los usuarios autenticados puedan usar SignalR?
  2. ¿Cómo obtengo la identidad del usuario que ha iniciado sesión actualmente desde el concentrador?

Algo que falta en las otras respuestas es la capacidad de usar las clases de autenticación personalizadas incorporadas en SignalR. La documentación real de SignalR sobre el tema es terrible, pero dejé un comentario en la parte inferior de la página que detalla cómo hacerlo en realidad ( Autenticación y autorización para concentradores SignalR ).

Básicamente, usted reemplaza la clase Autorizada de atributo de SignalR

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public class CustomAuthAttribute : AuthorizeAttribute

Luego, decora tus centros con [CustomAuth] sobre la declaración de clase. A continuación, puede anular los siguientes métodos para manejar auth:

bool AuthorizeHubConnection(HubDescriptor hubDesc, IRequest request); bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubContext, bool appliesToMethod);

Ya que estoy en los servidores IIS y tengo un esquema de autenticación personalizado, simplemente devuelvo true desde el método AuthorizeHubConnection, porque en mi Auth HttpModule ya autenticé las llamadas / signalr / connect y / signalr / reconnect y guardo los datos del usuario en un elemento HttpContext . Así que el módulo maneja la autenticación en la llamada de conexión SignalR inicial (una llamada HTTP estándar que inicia la conexión de socket web).

Para autorizar llamadas en métodos de hub específicos, reviso los nombres de los métodos con los permisos guardados en HttpContext (es el mismo HttpContext guardado desde la solicitud de conexión inicial) y devuelvo verdadero o falso en función de si el usuario tiene permiso para llamar a un determinado método.

En su caso, podría usar el método AuthorizeHubConnection y decorar sus métodos de hub con roles específicos, porque parece que está usando un sistema de identidad estandarizado, pero si algo no funciona bien, siempre puede volver a la fuerza bruta con HttpModule (u OWIN) middle-ware y buscar datos de contexto en las siguientes llamadas de websocket con AuthorizeHubMethodInvocation.


Para la parte 1. de su pregunta, puede usar anotaciones como las siguientes (esto funcionó con SignalR 1.1):

[Authorize] public class MyHub : Hub { public void MarkFilled(int id) { Clients.All.Filled(id); } public void MarkUnFilled(int id) { Clients.All.UnFilled(id); } }


Puede bloquear las URL de SignalR utilizando el evento PostAuthenticateRequest en su HttpApplication. Agregue lo siguiente a su Global.asax.cs

Esto bloqueará las solicitudes que no usen "https" o que no estén autenticadas.

public override void Init() { PostAuthenticateRequest += OnPostAuthenticateRequest; } private void OnPostAuthenticateRequest(object sender, EventArgs eventArgs) { if (Context.Request.Path.StartsWith("/signalr", StringComparison.OrdinalIgnoreCase)) { if(Context.Request.Url.Scheme != "https") { throw new HttpException(403, "Forbidden"); } if (!Context.User.Identity.IsAuthenticated) { throw new HttpException(403, "Forbidden"); } } }

Dentro de su hub puede acceder al usuario actual a través del objeto de contexto.

Context.User.Identity.Name


Debe usar this.Context.User.Identity que está disponible en el Hub. Ver una pregunta relacionada.

EDITAR: Para detener usuarios no autenticados:

public void ThisMethodRequiresAuthentication() { if(!this.Context.User.Identity.IsAuthenticated) { // possible send a message back to the client (and show the result to the user) this.Clients.SendUnauthenticatedMessage("You don''t have the correct permissions for this action."); return; } // user is authenticated continue }

EDITAR # 2: Esto podría ser mejor, simplemente devuelva un mensaje

public string ThisMethodRequiresAuthentication() { if(!this.Context.User.Identity.IsAuthenticated) { // possible send a message back to the client (and show the result to the user) return "You don''t have the correct permissions for this action."); // EDIT: or throw the 403 exception (like in the answer from Jared Kells (+1 from me for his answer), which I actually like better than the string) throw new HttpException(403, "Forbidden"); } // user is authenticated continue return "success"; }