.net core 3.0 Signalr - 05 使用jwt將使用者跟signalr關聯
阿新 • • 發佈:2019-12-31
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 業務實現-業務分析 |
原始碼地址 |
原始碼 |
官方檔案 |
官方檔案 |