通过SIgnalR Core中的用户名向特定用户发送消息

问题描述

我将SignalR Core添加到了Asp.net Core 3 Web Api项目中,该Web api与我的Android应用程序进行通信,我试图在两个客户端之间来回发送消息,并且我不想使用connection_Id因为当用户离开进行连接的活动时,如果客户端重新连接,连接将丢失并且connection_Id将更改,在这种情况下,两个用户间的通信将丢失,第二个用户将无法通信与第一个用户在一起,因为另一个用户的connectionId已更改,所以我想使用userName或userId在用户之间发送消息

PS:当我向所有客户端发送消息或使用connectionId发送代码时,效果很好。

PS:我正在使用身份和JWT对我的应用程序中的用户进行身份验证和授权。所以我在Hub中有此方法

public async Task sendOffer(DeliveryOffer offer)
        {

            string name= Context.User.Identity.Name;
            Notifications notification = new Notifications();
            notification.deliveryOffer = offer;
            await Clients.User(name).SendAsync("sendOfferToClient",notification);
        }

这是mycustomerUserIdProvider:

public class CustomUserIdProvider : IUserIdProvider
    {
        public virtual string GetUserId(HubConnectionContext connection)
        {

            return connection.User.Identity.Name;
        }
    }

在我的启动类的configure方法中,我在添加Authentication之后添加了signalR,如下所示:

app.UseAuthentication();
            app.UseAuthorization();
            
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            app.UseSignalR(routes => {
                routes.MapHub<NotificationHub>("/myHub");
            });

并在我的configureServices方法中:

            services.AddSignalR();
            services.AddSingleton<IUserIdProvider,CustomUserProvider>();

但是此指令始终返回null:

string id = Context.User.Identity.Name; // Always null

这是在我的控制器中生成令牌的方法

    private TokenResponse generatetoken(User user)
            {
                var tokenHandler = new JwtSecurityTokenHandler();
                var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret);
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new System.Security.Claims.ClaimsIdentity(new[]
                    {
                                    new Claim(JwtRegisteredClaimNames.Aud,user.Email),new Claim(JwtRegisteredClaimNames.Sub,new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),new Claim(JwtRegisteredClaimNames.Email,new Claim(JwtRegisteredClaimNames.UniqueName,user.UserName)
new Claim(JwtRegisteredClaimNames.NameId,user.UserName),new Claim(ClaimTypes.NameIdentifier,}),Expires = DateTime.UtcNow.AddMinutes(10),SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256)
                };
    
                var token = tokenHandler.Createtoken(tokenDescriptor);
    
                TokenResponse response = new TokenResponse();
                response.token = tokenHandler.Writetoken(token);
                return response;
            }

这是我的ConfigureServices方法

    public void ConfigureServices(IServiceCollection services)
            {
                JwtSettings jwtSettings = new JwtSettings();
                Http_Client http_client = new Http_Client();
                Configuration.Bind(nameof(jwtSettings),jwtSettings);
    
    
                services.AddIdentity<SuperUser,IdentityRole<int>>()
                .AddEntityFrameworkStores<AkdContext>()
                .AddUserManager<CustomUserManager>();
                services.Configure<IdentityOptions>(options =>
                {
                    
                });
    
              
                services.AddMvc(options => options.EnableEndpointRouting = false);
                services.AddAuthentication(x =>
                {
                    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                    .AddJwtBearer(x =>
                    {
                        x.Savetoken = true;
                        
                        x.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuerSigningKey = true,IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.Secret)),ValidateIssuer = false,ValidateAudience = false,Validissuer = Configuration["JwtSettings:Issuer"],ValidAudience = Configuration["JwtSettings:Issuer"],RequireExpirationTime = false,ClockSkew = TimeSpan.FromMinutes(60),ValidateLifetime = true,};
                        x.Events = new JwtBearerEvents
                        {
                            OnMessageReceived = context =>
                            {
                                var accesstoken = context.Request.Query["access_token"];
    
                                // If the request is for our hub...
                                var path = context.HttpContext.Request.Path;
                                if (!string.IsNullOrEmpty(accesstoken) &&
                                    (path.StartsWithSegments("/myHub")))
                                {
                                    // Read the token out of the query string
                                    context.Token = accesstoken;
                                }
                                return Task.CompletedTask;
                            }
                        };
    
                    });
    
                services.AddAuthorization();
    
                services.AddSingleton<IUserIdProvider,CustomUserProvider>();
                services.AddSignalR();
    
                services.AddMvc();
                services.AddDbContext<AkdContext>();
                
                services.AddControllers();
                services.AddSingleton(jwtSettings);
                services.AddTransient<IHttp_Client,Http_Client>();
    
                //services.AddTransient<ICommandRepository,CommandRepository>();
                //services.AddTransient<ICommandService,CommandService>();
                
    
                services.AddTransient<IOrderRequestRepository,OrderRequestRepository>();
                services.AddTransient<IOrderRequestService,OrderRequestService>();
    
                services.AddTransient<INotificationRepository,NotificationRepository>();
                services.AddTransient<INotificationService,NotificationService>();
    
                
                services.AddAutoMapper(typeof(Startup));
    
            }


and this is the Configure  method :

public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            
            app.UseEndpoints(endpoints =>
            {

                endpoints.MapControllers();
            });

            app.UseSignalR(routes => {
                routes.MapHub<NotificationHub>("/myHub");
            });
           

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",template: "{controller}/{action}/{id?}");
            });

            app.UseCors(x => x
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());

        }

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)