当我使用 C# 客户端时,为什么 SignalR hub 中的 Context.User 为空?

问题描述 投票:0回答:1

我有 ASP.NET MVC 应用程序,并且正在使用 SignalR 进行实时出价。我需要通过 JavaScript 和 C#(从我的一个控制器)使用客户端。

这是我的 Startup.cs 文件:


    namespace DesignAndBuilding.Web
{
    using System.Reflection;

    using AutoMapper;
    using DesignAndBuilding.Data;
    using DesignAndBuilding.Data.Common;
    using DesignAndBuilding.Data.Common.Repositories;
    using DesignAndBuilding.Data.Models;
    using DesignAndBuilding.Data.Repositories;
    using DesignAndBuilding.Data.Seeding;
    using DesignAndBuilding.Services;
    using DesignAndBuilding.Services.Mapping;
    using DesignAndBuilding.Services.Messaging;
    using DesignAndBuilding.Web.Hubs;
    using DesignAndBuilding.Web.ViewModels;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;

    public class Startup
    {
        private readonly IConfiguration configuration;

        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            services.AddDbContext<ApplicationDbContext>(
                options => options.UseSqlServer(this.configuration.GetConnectionString("DefaultConnection")));

            services.AddDefaultIdentity<ApplicationUser>(IdentityOptionsProvider.GetIdentityOptions)
                .AddRoles<ApplicationRole>().AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddSignalR(options =>
            {
                options.EnableDetailedErrors = true;
            })
            .AddMessagePackProtocol();

            services.Configure<CookiePolicyOptions>(
                options =>
                    {
                        options.CheckConsentNeeded = context => true;
                        options.MinimumSameSitePolicy = SameSiteMode.None;
                    });

            services.AddAutoMapper(typeof(Startup), typeof(MappingProfile));

            services.AddMemoryCache();

            services.AddControllersWithViews(
                options =>
                    {
                        options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
                    }).AddRazorRuntimeCompilation();
            services.AddRazorPages();
            services.AddDatabaseDeveloperPageExceptionFilter();

            services.AddSingleton(this.configuration);

            // Data repositories
            services.AddScoped(typeof(IDeletableEntityRepository<>), typeof(EfDeletableEntityRepository<>));
            services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
            services.AddScoped<IDbQueryRunner, DbQueryRunner>();

            // Application services
            services.AddTransient<IEmailSender, NullMessageSender>();
            services.AddTransient<IBuildingsService, BuildingsService>();
            services.AddTransient<IUsersService, UsersService>();
            services.AddTransient<IAssignmentsService, AssignmentsService>();
            services.AddTransient<IBidsService, BidsService>();
            services.AddTransient<INotificationsService, NotificationsService>();
            services.AddTransient<AuthenticationService>();

            // Auto Mapper Configurations
            services.AddSingleton(provider => new MapperConfiguration(mc =>
            {
                mc.AddProfile(new MappingProfile());
            }).CreateMapper());
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            AutoMapperConfig.RegisterMappings(typeof(ErrorViewModel).GetTypeInfo().Assembly);

            // Seed data on application startup
            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                var dbContext = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

                dbContext.Database.Migrate();

                new ApplicationDbContextSeeder().SeedAsync(dbContext, serviceScope.ServiceProvider).GetAwaiter().GetResult();
            }

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseMigrationsEndPoint();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(
                endpoints =>
                    {
                        endpoints.MapHub<NotificationsHub>("/notificationshub");
                        endpoints.MapHub<BidsHub>("/bidshub");
                        endpoints.MapControllerRoute("areaRoute", "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                        endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
                        endpoints.MapRazorPages();
                    });
        }
    }
}

这是我的 JS 客户端:

console.log('Bids script loaded successfully!');

setupConnection = async function start() {
    let connection = null;
    connection = await new signalR.HubConnectionBuilder()
        .withUrl("/bidshub")
        .build();

    await connection.on('newbidplaced', (obj) => {
        console.log(obj);
    })

    await connection.start()
        .catch(err => console.error(err.toString()))
        .then(() => {
            connection.invoke('NewBid', '1', 'testUser', 5.4);
        });
}

setupConnection();

这是我的一个控制器的 C# 客户端:

var connection = new HubConnectionBuilder()
    .AddMessagePackProtocol()
    .WithUrl($"https://{this.Request.Host}/bidshub", options =>
    {
        options.UseDefaultCredentials = true;
    })
    .WithAutomaticReconnect()
    .Build();
await connection.StartAsync();
await connection.InvokeAsync("NewBid", strId, user.Id, bidViewModel.BidPrice);
await connection.DisposeAsync();

我的问题是,当我使用 C# 客户端时,SignalR hub 中的 Context.User 始终为 null。但是,当我使用 JS 客户端时,用户已通过身份验证并且 Context.User 不为 null。有什么区别以及可能存在什么问题?

c# asp.net-core signalr.client asp.net-core-signalr
1个回答
0
投票

分析代码后,您使用cookie进行身份验证。默认情况下,支持

Javascript clients
(浏览器),但不支持
C# Clients

所以你应该获取 cookie 并在 C# 客户端中使用它,如下所示:

    var connection = new HubConnectionBuilder()
        .WithUrl("https://yourserver.com/bidshub", options =>
        {
            options.HttpMessageHandlerFactory = _ => new HttpClientHandler
            {
                CookieContainer = new System.Net.CookieContainer()
            };
            options.Headers["Cookie"] = cookie;
        })
        .Build();
© www.soinside.com 2019 - 2024. All rights reserved.