.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联
程序员文章站
2022-04-14 22:41:19
Signalr是以Group、Connect为核心来进行推送,比如,给某个组、某个连接来推送,但实际场景中,核心应该是某个组、某个人;然而一个人可以对应多个连接(浏览器多个tab页);本节就来介绍下自行管理人、组、连接这些关系 由于signalr连接的时候不那么方便附带header和cookie(因 ......
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 业务实现-业务分析 |
源码地址 | 源码 |
官方文档 | 官方文档 |