How to Make SignalR connection establishment When

2019-08-26 09:29发布

I want to make SignalR connection establishment when login to system,now it's doing separately.In .net core I used Microsoft.AspNetCore.SignalR package and in angular I used @aspnet/signalr.When user connect with signalR,then that user want to store in a list with connectionId and username.

Here is my login method in client side

login(model: any) {
    return this.http.post(this.baseUrl + 'login', model).pipe(
      map((response: any) => {
        const user = response;
        if (user) {
          localStorage.setItem('token', user.token);
          localStorage.setItem('user', JSON.stringify(user.user));
          localStorage.setItem('role', user.roles[0]);
          this.currentUser = user.user;
          this.decodedToken = this.jwtHelper.decodeToken(user.token);
          this.userRole = user.roles[0];
         this.changeMemberPhoto(this.currentUser.photoUrl);
        }
      })
    );
  }

this is server side login method

[HttpPost("login")]
        public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
        {
            try
            {
                var loggedUser = await _userManager.FindByNameAsync(userForLoginDto.Username);
                var result = await _signInManager.CheckPasswordSignInAsync(loggedUser, userForLoginDto.Password, false);

                if (result.Succeeded)
                {
                    var appUser = await _userManager.Users.Include(p => p.Photos).Include(r => r.UserRoles)
                    .FirstOrDefaultAsync(u => u.NormalizedUserName == userForLoginDto.Username.ToUpper());

                    var selectedUser = await _userManager.FindByNameAsync(appUser.UserName);
                    // Get the roles for the user
                    var roles = await _userManager.GetRolesAsync(selectedUser);




                    var userToReturn = _mapper.Map<UserForListDto>(appUser);
                    var generatedToken = GenerateJwtToken(appUser);

                    return Ok(new
                    {
                        token = generatedToken.Result,
                        user = userToReturn,
                        roles = roles
                    });
                }

                return Unauthorized();
            }
            catch (Exception e)
            {
                return BadRequest("An error occurs while loggin:" + e.ToString());
            }

        }

        private async Task<string> GenerateJwtToken(User user)
        {
            var claims = new List<Claim> {
                new Claim(ClaimTypes.NameIdentifier,user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.UserName)
        };

            var roles = await _userManager.GetRolesAsync(user);

            foreach (var role in roles)
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8
            .GetBytes(_config.GetSection("AppSettings:Token").Value));

            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

            var tokenDescripter = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.Now.AddDays(1),
                SigningCredentials = creds
            };

            var tokenHandler = new JwtSecurityTokenHandler();

            var token = tokenHandler.CreateToken(tokenDescripter);

            return tokenHandler.WriteToken(token);
        }

this is my startup class code

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<DataContext>(s => s.UseMySql(Configuration.GetConnectionString("DefaultConnection"))
            .ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)));
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    policy => policy.AllowAnyMethod()
                        .AllowAnyHeader()
                        .WithOrigins("http://localhost:4200")
                        .AllowCredentials());
            });
            services.AddSignalR();

            services.AddMvc()
                        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                        .AddJsonOptions(opt =>
                        {
                            opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                        });

            services.AddAutoMapper();
            services.AddTransient<Seed>();
            services.AddScoped<IAuthRepository, AuthRepository>();
            services.AddScoped<IDatingRepository, DatingRepository>();
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
                      .GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });
            services.AddScoped<LogUserActivity>();



            IdentityBuilder builder = services.AddIdentityCore<User>(opt =>
            {
                opt.Password.RequireDigit = false;
                opt.Password.RequiredLength = 4;
                opt.Password.RequireNonAlphanumeric = false;
                opt.Password.RequireUppercase = false;

            });

            builder = new IdentityBuilder(builder.UserType, typeof(Role), builder.Services);
            builder.AddEntityFrameworkStores<DataContext>();
            builder.AddRoleValidator<RoleValidator<Role>>();
            builder.AddRoleManager<RoleManager<Role>>();
            builder.AddSignInManager<SignInManager<User>>();



            // services.AddAuthorization(options => {
            //     options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
            //     options.AddPolicy("SuperAdminPhotoRole", policy => policy.RequireRole("SuperAdmin"));
            // });


            // services.AddCors();


        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, Seed seeder, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"))
                .AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {

                app.UseExceptionHandler(builder =>
                {
                    builder.Run(async context =>
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                        var error = context.Features.Get<IExceptionHandlerFeature>();
                        if (error != null)
                        {
                            context.Response.AddApplicationError(error.Error.Message);
                            await context.Response.WriteAsync(error.Error.Message);
                        }
                    });
                });

                // app.UseHsts();
            }

            // app.UseHttpsRedirection();
            seeder.SeedUsers();
            app.UseCors("CorsPolicy");
            //app.UseCors(x => x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
            app.UseSignalR(routes =>
                  {
                      routes.MapHub<MessageHub>("/hub");
                  });
            app.UseAuthentication();
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Fallback", action = "Index" }
                );
            });
        }
    }

This is the code for SignalR in client side

export class HubconnectionService {
  _hubConnection: HubConnection;
  baseUrl = environment.apiUrl;
  constructor() {
    this._hubConnection = new HubConnectionBuilder()
      .withUrl(this.baseUrl + 'hub')
      .build();
  }

  public startConnection() {
    this._hubConnection.start().catch(err => document.write(err));
  }
}

here is my Hub class in .net core

public class MessageHub : Hub
    {
        List<UserConnection> uList = new List<UserConnection>();
        public async Task NewMessage(string username, string message)
        {
            var user = uList.Where(o => o.UserName == username);
            if (user.Any())
            {
                await Clients.Client(user.First().ConnectionID).SendAsync("messageReceived", username, message);
            }

        }
        public override async Task OnConnectedAsync()
        {
           string name = Context.User.Identity.Name;
            var us = new UserConnection();
            us.UserName = name;
            us.ConnectionID = Context.ConnectionId;
            uList.Add(us);

            await base.OnConnectedAsync();
        }


    }

please help me

0条回答
登录 后发表回答