Skip to content

Commit 4e25a91

Browse files
committed
Added tests to handle client authentication.
1 parent b451516 commit 4e25a91

File tree

5 files changed

+161
-146
lines changed

5 files changed

+161
-146
lines changed

WebSocketSharp.Tests/WebSocketServerTests.cs

Lines changed: 138 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,19 @@ namespace WebSocketSharp.Tests
2828
using NUnit.Framework;
2929
using NUnit.Framework.Constraints;
3030

31+
using WebSocketSharp.Net;
3132
using WebSocketSharp.Server;
3233

3334
public sealed class WebSocketServerTests
3435
{
35-
public class GivenAWebSocketServer
36+
public abstract class GivenAWebSocketServer
3637
{
3738
private const string WsLocalhostRadio = "ws://localhost:8080/radio";
3839
private const string WsLocalhostEcho = "ws://localhost:8080/echo";
3940
private const string Message = "Message";
40-
private WebSocketServer _sut;
41+
protected WebSocketServer _sut;
4142

42-
[SetUp]
43-
public void Setup()
44-
{
45-
Debug.Listeners.Add(new ConsoleTraceListener());
46-
_sut = new WebSocketServer(port: 8080);
47-
_sut.AddWebSocketService<TestEchoService>("/echo");
48-
_sut.AddWebSocketService<TestRadioService>("/radio");
49-
_sut.Start();
50-
}
51-
52-
[TearDown]
53-
public async Task Teardown()
54-
{
55-
await _sut.Stop().ConfigureAwait(false);
56-
Debug.Listeners.Clear();
57-
}
43+
protected abstract void SetCredentials(WebSocket ws);
5844

5945
[Test]
6046
public void CanGetDefinedPort()
@@ -67,6 +53,7 @@ public async Task ClientCanConnectToServer()
6753
{
6854
using (var client = new WebSocket(WsLocalhostEcho))
6955
{
56+
SetCredentials(client);
7057
await client.Connect().ConfigureAwait(false);
7158

7259
Assert.AreEqual(WebSocketState.Open, client.ReadyState);
@@ -76,10 +63,10 @@ public async Task ClientCanConnectToServer()
7663
[Test]
7764
public async Task WhenClientSendsTextMessageThenResponds()
7865
{
79-
const string Message = "Message";
8066
var waitHandle = new ManualResetEventSlim(false);
8167
using (var client = new WebSocket(WsLocalhostEcho))
8268
{
69+
SetCredentials(client);
8370
Func<MessageEventArgs, Task> onMessage = e =>
8471
{
8572
if (e.Text.ReadToEnd() == Message)
@@ -105,6 +92,7 @@ public async Task WhenClientConnectsToNonExistingPathThenStateIsClosed()
10592
{
10693
using (var client = new WebSocket("ws://localhost:8080/fjgkdfjhgld"))
10794
{
95+
SetCredentials(client);
10896
await client.Connect().ConfigureAwait(false);
10997

11098
Assert.True(client.ReadyState == WebSocketState.Closed);
@@ -117,18 +105,20 @@ public Task WhenClientConnectsToNonExistingPathThenDoesNotThrow()
117105
{
118106
using (var client = new WebSocket("ws://localhost:8080/fjgkdfjhgld"))
119107
{
108+
SetCredentials(client);
120109
Assert.That(async () => await client.Connect().ConfigureAwait(false), new ThrowsNothingConstraint());
121110
}
122111
return Task.FromResult(true);
123112
}
124113

125114
[Test]
126-
public async Task WhenClientSendsMultipleAsyncTextMessageThenResponds([Random(1, 100, 10)]int multiplicity)
115+
public async Task WhenClientSendsMultipleAsyncTextMessageThenResponds([Random(1, 100, 10)] int multiplicity)
127116
{
128117
int count = 0;
129118
var waitHandle = new ManualResetEventSlim(false);
130119
using (var client = new WebSocket(WsLocalhostEcho))
131120
{
121+
SetCredentials(client);
132122
Func<MessageEventArgs, Task> onMessage = e =>
133123
{
134124
if (e.Text.ReadToEnd() == Message)
@@ -155,28 +145,29 @@ public async Task WhenClientSendsMultipleAsyncTextMessageThenResponds([Random(1,
155145
}
156146

157147
[Test]
158-
public async Task WhenStreamVeryLargeStreamToServerThenResponds([Random(750000, 1500000, 5)]int length)
148+
public async Task WhenStreamVeryLargeStreamToServerThenResponds([Random(750000, 1500000, 5)] int length)
159149
{
160150
var responseLength = 0;
161151

162152
var stream = new EnumerableStream(Enumerable.Repeat((byte)123, length));
163153
var waitHandle = new ManualResetEventSlim(false);
164154
using (var client = new WebSocket(WsLocalhostEcho))
165155
{
156+
SetCredentials(client);
166157
Func<MessageEventArgs, Task> onMessage = async e =>
167-
{
168-
var bytesRead = 0;
169-
var readLength = 10240000;
170-
do
171158
{
172-
var buffer = new byte[readLength];
173-
bytesRead = await e.Data.ReadAsync(buffer, 0, readLength).ConfigureAwait(false);
174-
responseLength += buffer.Count(x => x == 123);
175-
}
176-
while (bytesRead == readLength);
159+
var bytesRead = 0;
160+
var readLength = 10240000;
161+
do
162+
{
163+
var buffer = new byte[readLength];
164+
bytesRead = await e.Data.ReadAsync(buffer, 0, readLength).ConfigureAwait(false);
165+
responseLength += buffer.Count(x => x == 123);
166+
}
167+
while (bytesRead == readLength);
177168

178-
waitHandle.Set();
179-
};
169+
waitHandle.Set();
170+
};
180171

181172
client.OnMessage = onMessage;
182173

@@ -191,7 +182,7 @@ public async Task WhenStreamVeryLargeStreamToServerThenResponds([Random(750000,
191182

192183
[Test]
193184
[Timeout(60000)]
194-
public async Task WhenStreamVeryLargeStreamToServerThenBroadcasts([Random(750000, 1500000, 5)]int length)
185+
public async Task WhenStreamVeryLargeStreamToServerThenBroadcasts([Random(750000, 1500000, 5)] int length)
195186
{
196187
var responseLength = 0;
197188

@@ -200,14 +191,16 @@ public async Task WhenStreamVeryLargeStreamToServerThenBroadcasts([Random(750000
200191

201192
using (var sender = new WebSocket(WsLocalhostRadio))
202193
{
194+
SetCredentials(sender);
203195
using (var client = new WebSocket(WsLocalhostRadio))
204196
{
197+
SetCredentials(client);
205198
Func<MessageEventArgs, Task> onMessage = async e =>
206-
{
207-
var bytes = await e.Data.ReadBytes(length).ConfigureAwait(false);
208-
responseLength = bytes.Count(x => x == 123);
209-
waitHandle.Set();
210-
};
199+
{
200+
var bytes = await e.Data.ReadBytes(length).ConfigureAwait(false);
201+
responseLength = bytes.Count(x => x == 123);
202+
waitHandle.Set();
203+
};
211204

212205
client.OnMessage = onMessage;
213206

@@ -233,6 +226,7 @@ public async Task CanSendTwentyThousandSynchronousRequestsPerSecond()
233226
var waitHandle = new ManualResetEventSlim(false);
234227
using (var client = new WebSocket(WsLocalhostEcho))
235228
{
229+
SetCredentials(client);
236230
const int Multiplicity = 20000;
237231
Func<MessageEventArgs, Task> onMessage = e =>
238232
{
@@ -270,6 +264,7 @@ public async Task CanReceiveTwentyFiveThousandSynchronousRequestsInSixSeconds()
270264
var waitHandle = new ManualResetEventSlim(false);
271265
using (var client = new WebSocket(WsLocalhostEcho))
272266
{
267+
SetCredentials(client);
273268
const int Multiplicity = 25000;
274269
Func<MessageEventArgs, Task> onMessage = async e =>
275270
{
@@ -309,6 +304,7 @@ public async Task CanSendOneMillionAsynchronousRequestsPerSecond()
309304
var waitHandle = new ManualResetEventSlim(false);
310305
using (var client = new WebSocket(WsLocalhostEcho))
311306
{
307+
SetCredentials(client);
312308
const int Multiplicity = (int)1E3;
313309

314310
client.OnMessage = e => Task.FromResult(true);
@@ -323,7 +319,10 @@ public async Task CanSendOneMillionAsynchronousRequestsPerSecond()
323319

324320
waitHandle.Wait(Debugger.IsAttached ? 30000 : 5000);
325321

326-
Assert.LessOrEqual(stopwatch.Elapsed, TimeSpan.FromSeconds(1), "Total time taken: " + stopwatch.Elapsed);
322+
Assert.LessOrEqual(
323+
stopwatch.Elapsed,
324+
TimeSpan.FromSeconds(1),
325+
"Total time taken: " + stopwatch.Elapsed);
327326
}
328327
}
329328

@@ -338,33 +337,114 @@ public async Task CanReceiveOneMillionAsynchronousResponsesInTenSecond()
338337
var stream = new MemoryStream(Encoding.UTF8.GetBytes(Message));
339338
var length = (int)stream.Length;
340339
var waitHandle = new ManualResetEventSlim(false);
341-
var client = new WebSocket(WsLocalhostEcho);
342-
343-
const int Multiplicity = 1000000;
344-
Func<MessageEventArgs, Task> onMessage = async e =>
345-
{
346-
if (await e.Text.ReadToEndAsync().ConfigureAwait(false) == Message && Interlocked.Increment(ref count) == Multiplicity)
340+
using (var client = new WebSocket(WsLocalhostEcho))
341+
{
342+
SetCredentials(client);
343+
const int Multiplicity = 1000000;
344+
Func<MessageEventArgs, Task> onMessage = async e =>
347345
{
348-
responseWatch.Stop();
349-
waitHandle.Set();
350-
}
351-
};
352-
client.OnMessage = onMessage;
346+
if (await e.Text.ReadToEndAsync().ConfigureAwait(false) == Message
347+
&& Interlocked.Increment(ref count) == Multiplicity)
348+
{
349+
responseWatch.Stop();
350+
waitHandle.Set();
351+
}
352+
};
353+
client.OnMessage = onMessage;
353354

354-
await client.Connect().ConfigureAwait(false);
355-
responseWatch.Start();
355+
await client.Connect().ConfigureAwait(false);
356+
responseWatch.Start();
356357

357-
var tasks = Enumerable.Range(0, Multiplicity).Select(x => client.Send(stream, length));
358+
var tasks = Enumerable.Range(0, Multiplicity).Select(x => client.Send(stream, length));
358359

359-
await Task.WhenAll(tasks).ConfigureAwait(false);
360+
await Task.WhenAll(tasks).ConfigureAwait(false);
360361

361-
waitHandle.Wait();
362+
waitHandle.Wait();
362363

363-
Console.WriteLine(responseWatch.Elapsed);
364+
Console.WriteLine(responseWatch.Elapsed);
364365

365-
Assert.LessOrEqual(responseWatch.Elapsed, TimeSpan.FromSeconds(10));
366+
Assert.LessOrEqual(responseWatch.Elapsed, TimeSpan.FromSeconds(10));
367+
}
368+
}
369+
}
366370

367-
client.Dispose();
371+
[TestFixture]
372+
public class GivenAWebSocketServerAllowingAnonymousConnections : GivenAWebSocketServer
373+
{
374+
[SetUp]
375+
public void Setup()
376+
{
377+
Debug.Listeners.Add(new ConsoleTraceListener());
378+
_sut = new WebSocketServer(port: 8080);
379+
_sut.AddWebSocketService<TestEchoService>("/echo");
380+
_sut.AddWebSocketService<TestRadioService>("/radio");
381+
_sut.Start();
382+
}
383+
384+
[TearDown]
385+
public async Task Teardown()
386+
{
387+
await _sut.Stop().ConfigureAwait(false);
388+
Debug.Listeners.Clear();
389+
}
390+
391+
protected override void SetCredentials(WebSocket ws)
392+
{
393+
}
394+
}
395+
396+
[TestFixture]
397+
public class GivenAWebSocketServerUsingBasicAuthentication : GivenAWebSocketServer
398+
{
399+
[SetUp]
400+
public void Setup()
401+
{
402+
Debug.Listeners.Add(new ConsoleTraceListener());
403+
_sut = new WebSocketServer(port: 8080, authenticationSchemes: AuthenticationSchemes.Basic);
404+
_sut.UserCredentialsFinder = id => new NetworkCredential(id.Name, "password");
405+
_sut.AddWebSocketService<TestEchoService>("/echo");
406+
_sut.AddWebSocketService<TestRadioService>("/radio");
407+
_sut.Start();
408+
}
409+
410+
[TearDown]
411+
public async Task Teardown()
412+
{
413+
await _sut.Stop().ConfigureAwait(false);
414+
Debug.Listeners.Clear();
415+
}
416+
417+
protected override void SetCredentials(WebSocket ws)
418+
{
419+
ws.SetCredentials("username", "password", true);
420+
}
421+
}
422+
423+
[TestFixture]
424+
public class GivenAWebSocketServerUsingDigestAuthentication : GivenAWebSocketServer
425+
{
426+
[SetUp]
427+
public void Setup()
428+
{
429+
Debug.Listeners.Add(new ConsoleTraceListener());
430+
_sut = new WebSocketServer(port: 8080, authenticationSchemes: AuthenticationSchemes.Digest);
431+
_sut.UserCredentialsFinder = id => new NetworkCredential(id.Name, "password", "Test");
432+
_sut.Realm = "Test";
433+
_sut.AddWebSocketService<TestEchoService>("/echo");
434+
_sut.AddWebSocketService<TestRadioService>("/radio");
435+
_sut.Start();
436+
}
437+
438+
[TearDown]
439+
public async Task Teardown()
440+
{
441+
await _sut.Stop().ConfigureAwait(false);
442+
Debug.Listeners.Clear();
443+
}
444+
445+
protected override void SetCredentials(WebSocket ws)
446+
{
447+
ws.SetCredentials("username", "password", true);
368448
}
369449
}
370450
}

websocket-sharp.clone/Net/WebSockets/TcpListenerWebSocketContext.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,8 @@ internal void SetUser(
282282
Func<IIdentity, NetworkCredential> credentialsFinder)
283283
{
284284
var authRes = _request.AuthenticationResponse;
285-
if (authRes == null)
286-
{
287-
return;
288-
}
289285

290-
var id = authRes.ToIdentity();
286+
var id = authRes?.ToIdentity();
291287
if (id == null)
292288
{
293289
return;
@@ -302,13 +298,14 @@ internal void SetUser(
302298
{
303299
}
304300

305-
if (cred == null) return;
301+
if (cred == null)
302+
{
303+
return;
304+
}
306305

307306
var valid = scheme == AuthenticationSchemes.Basic
308307
? ((HttpBasicIdentity)id).Password == cred.Password
309-
: scheme == AuthenticationSchemes.Digest
310-
? ((HttpDigestIdentity)id).IsValid(cred.Password, realm, _request.HttpMethod, null)
311-
: false;
308+
: scheme == AuthenticationSchemes.Digest && ((HttpDigestIdentity)id).IsValid(cred.Password, realm, _request.HttpMethod, null);
312309

313310
if (valid) _user = new GenericPrincipal(id, cred.Roles);
314311
}

0 commit comments

Comments
 (0)