1. 程式人生 > 程式設計 >.net core 3.0 Signalr - 05 使用jwt將使用者跟signalr關聯

.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 業務實現-業務分析
原始碼地址
原始碼
官方檔案
官方檔案

二維碼