I'm using asp.net boilerplate framework, and I'm trying to set the WebSocket connection to become match the logged-in user id when the user establishes the WebSocket connection, but what I noticed is the AbpSession.UserId value is always null, so what is the reason, although in other classes it is working fine, and here is my code:
public class WebSocketServerConnectionManager : ITransientDependency
{
private ConcurrentDictionary<string, WebSocket> _socket = new ConcurrentDictionary<string, WebSocket>();
public IAbpSession AbpSession { get; set; }
public WebSocketServerConnectionManager()
{
AbpSession = NullAbpSession.Instance;
}
public ConcurrentDictionary<string, WebSocket> GetAllSockets()
{
return _socket;
}
public string AddSocket(WebSocket socket)
{
try
{
var ConnId = AbpSession.UserId.ToString(); //<==== Null
// Guid.NewGuid().ToString();
//var test = AbpSession.UserId;
_socket.TryAdd(ConnId/*dictionary item key*/, socket/*dictionary item value*/);
Debug.WriteLine("Connection Added:" ConnId);
return ConnId;
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
}
}
Update 1:
And here is the client-side WebSocket initialization:
async ngOnInit() {
this.connectWebSocket();
}
connectWebSocket(){
this.socket=new WebSocket(this.webSocketUrl);
this.socket.onopen=(event)=>{
}
this.socket.onclose=(event)=>{
}
this.socket.onmessage=(event)=>{
this.isConnID(event.data);
}
}
Update 2: Update3:
I have this in AuthConfigurer:
/* This method is needed to authorize SignalR javascript client.
* SignalR can not send authorization header. So, we are getting it from query string as an encrypted text. */
private static Task QueryStringTokenResolver(MessageReceivedContext context)
{
var test = context.HttpContext.Request.Path.Value;//the value is null
if (!context.HttpContext.Request.Path.HasValue ||
(!context.HttpContext.Request.Path.Value.StartsWith("/signalr") && !context.HttpContext.Request.Path.Value.StartsWith("/ws")))
{
// We are just looking for signalr clients
return Task.CompletedTask;
}
var qsAuthToken = context.HttpContext.Request.Query["enc_auth_token"].FirstOrDefault();
if (qsAuthToken == null)
{
// Cookie value does not matches to querystring value
return Task.CompletedTask;
}
// Set auth token from cookie
context.Token = SimpleStringCipher.Instance.Decrypt(qsAuthToken, AppConsts.DefaultPassPhrase);
return Task.CompletedTask;
}
and in appsettings.json the Authentication section :
"Authentication": {
"JwtBearer": {
"IsEnabled": "true",
"SecurityKey": "Test_C421AAEE0D114E9C",
"Issuer": "Test",
"Audience": "Test"
}
},
CodePudding user response:
You need to pass authentication information.
- If you're using the ASP.NET Boilerplate Angular template (with Module Zero), you may pass
enc_auth_token
in the query string, which will be resolved byQueryStringTokenResolver
.
// import { AppConsts } from '@shared/AppConsts';
// import { UtilsService } from 'abp-ng2-module';
connectWebSocket(){
// this.socket=new WebSocket(this.webSocketUrl); // Change this to the following
const encryptedAuthToken = new UtilsService().getCookieValue(AppConsts.authorization.encryptedAuthTokenName);
const webSocketUrl = this.webSocketUrl '?enc_auth_token=' encodeURIComponent(encryptedAuthToken);
this.socket = new WebSocket(webSocketUrl);
...
}
Reference: SignalRAspNetCoreHelper.ts
- If
webSocketUrl
doesn't start with/signalr
, whitelist it inQueryStringTokenResolver
:
private static Task QueryStringTokenResolver(MessageReceivedContext context)
{
if (!context.HttpContext.Request.Path.HasValue ||
// !context.HttpContext.Request.Path.Value.StartsWith("/signalr")) // Change this to the following
(!context.HttpContext.Request.Path.Value.StartsWith("/signalr") &&
!context.HttpContext.Request.Path.Value.StartsWith(webSocketUrl))
{
// ...
return Task.CompletedTask;
}
...
}
Remember to add the WebSockets middleware if you're using raw WebSockets.
- Add
app.UseWebSockets()
beforeapp.UseEndpoints(...)
in Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseWebSockets() // Add this
app.UseEndpoints(...
...
}
References: