.net core 3.0 Signalr - 05 使用jwt將用戶跟signalr關聯


Signalr是以Group、Connect為核心來進行推送,比如,給某個組、某個連接來推送,但實際場景中,核心應該是某個組、某個人;然而一個人可以對應多個連接(瀏覽器多個tab頁);本節就來介紹下自行管理人、組、連接這些關系
由於signalr連接的時候不那么方便附帶header和cookie(因為推送獨立成一個子系統了),實際實現中采用以url query的形式附帶上token,然后服務器端自定義解析token得到用戶信息;

服務器端實現

  • ConfigureServices中添加服務相關方法,代碼如下,完整代碼
    public void ConfigureServices(IServiceCollection services)
    {
        var appSection = Configuration.GetSection("App");
        services.Configure<AppSetting>(option => appSection.Bind(option));
        var appSetting = appSection.Get<AppSetting>();
    
        services.AddSingleton<SignalrRedisHelper>();
    
        // services.AddHostedService<ClearBackGroundService>();
    
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(option =>
        {
            option.SecurityTokenValidators.Clear();
            option.SecurityTokenValidators.Add(new UserTokenValidation()); ;
    
            option.Events = new JwtBearerEvents()
            {
                OnMessageReceived = context =>
                {
                    var userId = context.Request.Query["userId"].FirstOrDefault();
                    if (!string.IsNullOrWhiteSpace(userId))
                    {
                        context.Token = userId;
                    }
                    return Task.CompletedTask;
                }
            };
        });
    
        services.AddCors(options => options.AddPolicy(corsPolicy, builder =>
        {
            builder
                  .SetIsOriginAllowedToAllowWildcardSubdomains()
                  .WithOrigins(appSetting.CORS.Split(","))
                  .AllowAnyMethod()
                  .AllowCredentials()
                  .AllowAnyHeader()
                  .Build();
        }));
    
        services.AddControllers()
            .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver())
            .ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = context =>
                {
                    var result = new BadRequestObjectResult(context.ModelState);
                    result.ContentTypes.Add(MediaTypeNames.Application.Json);
                    // result.ContentTypes.Add(MediaTypeNames.Application.Xml);
    
                    return result;
                };
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
    
        // 添加Signalr
        services.AddSignalR(config =>
        {
            if (_webEnv.IsDevelopment())
            {
                config.EnableDetailedErrors = true;
            }
        })
        // 支持MessagePack
        .AddMessagePackProtocol()
        // 使用redis做底板 支持橫向擴展 Scale-out
        .AddStackExchangeRedis(o =>
          {
              o.ConnectionFactory = async writer =>
              {
                  var config = new ConfigurationOptions
                  {
                      AbortOnConnectFail = false,
                      // Password = "changeme",
                      ChannelPrefix = "__signalr_",
                  };
                  //config.EndPoints.Add(IPAddress.Loopback, 0);
                  //config.SetDefaultPorts();
                  config.DefaultDatabase = appSetting.SignalrRedisCache.DatabaseId;
                  var connection = await ConnectionMultiplexer.ConnectAsync(appSetting.SignalrRedisCache.ConnectionString, writer);
                  connection.ConnectionFailed += (_, e) =>
                  {
                      Console.WriteLine("Connection to Redis failed.");
                  };
    
                  if (connection.IsConnected)
                  {
                      Console.WriteLine("connected to Redis.");
                  }
                  else
                  {
                      Console.WriteLine("Did not connect to Redis");
                  }
    
                  return connection;
              };
          });
    }
    

其中,SignalrRedisHelper 為redis輔助方法,詳情請參見
UserTokenValidation 為自定義token解析方法,詳情請參見,由於歷史遺留問題,此處直接使用了userId,建議的做法是傳遞jwttoken,然后服務器端解析jwt token得到用戶信息

Hub中跟用戶關聯

在Hub中通過Context.User.Identity.Name可以獲取到解析的值,通過這種關系來跟用戶關聯上,當然,也可以自定義修改使用其他信息,比如Email或其他自定義的名稱,具體請google

更多內容請通過快速導航查看下一篇

快速導航

標題 內容
索引 .net core 3.0 Signalr - 實現一個業務推送系統
上一篇 .net core 3.0 Signalr - 04 使用Redis做底板來支持橫向擴展
下一篇 .net core 3.0 Signalr - 06 業務實現-業務分析
源碼地址 源碼
官方文檔 官方文檔

二維碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM