首页 > 解决方案 > 验证信号器集线器连接

问题描述

****我使用的是.Net框架,而不是核心****

我有一个连接到服务器并订阅一些 Hub 功能的 Web 界面。我正在尝试找到一种方法来限制对服务器的订阅,因此只有具有正确令牌的客户端才能连接和订阅。

这是我的服务器端:Startup.cs:

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
                map.UseCors(CorsOptions.AllowAll);
                var hubConfiguration = new HubConfiguration
                {
                    EnableDetailedErrors = true
                };
                map.RunSignalR(hubConfiguration);
            });
        }
    }

我的集线器类:

[HubName("CordioHub")]
    public class CordioHub : Hub
    {
        private static IHubContext CordioHubContext
        {
            get
            {
                return GlobalHost.ConnectionManager.GetHubContext<CordioHub>();
            }
        }

        public static void UpdateClient(string message)
        {
            CordioHubContext.Clients.All.UpdateClient(message);
        }

        public override Task OnDisconnected(bool stopCalled)
        {
            return Clients.All.leave(Context.ConnectionId, DateTime.Now.ToString());
        }

        public override Task OnConnected()
        {
            return Clients.All.joined(Context.ConnectionId, DateTime.Now.ToString());
        }

        public override Task OnReconnected()
        {
            return Clients.All.rejoined(Context.ConnectionId, DateTime.Now.ToString());
        }

        //Status page events:
        public static void UpdatePatientCout(int delta)
        {
            CordioHubContext.Clients.All.UpdatePatientCout(delta);
        }
    }

还有我的客户信号服务:

import { Injectable, Inject } from '@angular/core';

// declare the global variables  
declare var $: any;
@Injectable()
export class SignalRService {
    // Declare the variables  
    private proxy: any;
    private proxyName: string = 'CordioHub';
    private connection: any;
    // create the Event Emitter  
    public connectionExists: Boolean;

    constructor(@Inject('BASE_URL') private originUrl: string) {
        // Constructor initialization  
        this.connectionExists = false;
        // create hub connection  
        this.connection = $.hubConnection(originUrl + '/signalr');

        // add access token to connection
        this.addAccessToken();

        // create new proxy as name already given in top  
        this.proxy = this.connection.createHubProxy(this.proxyName);
        // register on server events  
        this.registerOnServerEvents();
        // call the connecion start method to start the connection to send and receive events.  
        this.startConnection();
    }


    // check in the browser console for either signalr connected or not  
    private startConnection(): void {
        this.connection.start().done((data: any) => {
            console.log('Now connected ' + data.transport.name + ', connection ID= ' + data.id);
            this.connectionExists = true;
        }).fail((error: any) => {
            console.log('Could not connect ' + error);
        });
    }

     private addAccessToken(): void {
         let token = this.getToken();
         this.connection.qs = {
             "access_token": token
         };
     }

    private registerOnServerEvents(): void {
        this.proxy.on('UpdateClient', (data: string) => {
            console.log('received in SignalRService: ' + JSON.stringify(data));
        });

        this.proxy.on('leave', (connectionId: string, date: Date) => {
            console.log('received in SignalRService: ' + connectionId + ' time: ' + date);
        });

        this.proxy.on('joined', (connectionId: string, date: Date) => {
            console.log('received in SignalRService: ' + connectionId + ' time: ' + date);
        });

        this.proxy.on('rejoined', (connectionId: string, date: Date) => {
            console.log('received in SignalRService: ' + connectionId + ' time: ' + date);
        });
    }

     private getToken(): string {
         if (localStorage.getItem('currentUser')) {
             return JSON.parse(localStorage.getItem('currentUser')).AccessToken;
         }
     }
}

正如我所解释的,我想在客户端尝试建立第一个连接时检查服务器端的令牌,并在令牌不好的情况下拒绝。非常感谢!

标签: c#.netsignalrangular7

解决方案


在这种情况下,您可以使用 JWT 令牌。配置真的很简单:

Program.cs你应该配置 JWT:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services
            .AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(cfg =>
            {
                cfg.RequireHttpsMetadata = false;
                cfg.SaveToken = true;
                cfg.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer = configuration["Jwt:Issuer"],
                    ValidAudience = configuration["Jwt:Issuer"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"])),
                    ClockSkew = TimeSpan.Zero
                };
                cfg.Events = new JwtBearerEvents
                {
                    OnMessageReceived = context =>
                    {
                        if (context.Request.Query.TryGetValue("token", out var token)
                        )
                            context.Token = token;

                        return Task.CompletedTask;
                    }
                };
            });

配置文件:

 "Jwt": {
    "Key": "someKey",
    "Issuer": "http://yourdomain.com",
    "ExpireDays": 0,
    "ExpireHours": 1,
    "ExpireMinutes": 0
},

在 Angular 中,您应该创建拦截器,它将向每个请求添加 Authentications 标头:

@Injectable()
export class JwtInterceptor implements HttpInterceptor {
    constructor(private userContext: UserContext) { }

intercept(
    request: HttpRequest<any>,
    next: HttpHandler
): Observable<HttpEvent<any>> {
    const authToken = this.userContext.getToken();
    if (!!authToken) {
        request = request.clone({
            setHeaders: {
                Authorization: `Bearer ${authToken}`
            }
        });
    }

    return next.handle(request);
    }
}

推荐阅读