Modified cookies validation, and added origin header validation
This commit is contained in:
parent
12efc99805
commit
048627b4f9
@ -16,16 +16,5 @@ namespace Example2
|
|||||||
|
|
||||||
Send (msg);
|
Send (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool ValidateCookies (
|
|
||||||
CookieCollection request, CookieCollection response)
|
|
||||||
{
|
|
||||||
foreach (Cookie cookie in request) {
|
|
||||||
cookie.Expired = true;
|
|
||||||
response.Add (cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,48 @@ namespace Example2
|
|||||||
|
|
||||||
wssv.AddWebSocketService<Echo> ("/Echo");
|
wssv.AddWebSocketService<Echo> ("/Echo");
|
||||||
wssv.AddWebSocketService<Chat> ("/Chat");
|
wssv.AddWebSocketService<Chat> ("/Chat");
|
||||||
//wssv.AddWebSocketService<Chat> (
|
|
||||||
// "/Chat",
|
/* With initializing
|
||||||
// () => new Chat ("Anon#") { Protocol = "chat" });
|
wssv.AddWebSocketService<Echo> (
|
||||||
|
"/Echo",
|
||||||
|
() => new Echo () {
|
||||||
|
Protocol = "echo",
|
||||||
|
OriginValidator = value => {
|
||||||
|
Uri origin;
|
||||||
|
return !value.IsNullOrEmpty () &&
|
||||||
|
Uri.TryCreate (value, UriKind.Absolute, out origin) &&
|
||||||
|
origin.Host == "localhost";
|
||||||
|
},
|
||||||
|
CookiesValidator = (req, res) => {
|
||||||
|
foreach (Cookie cookie in req) {
|
||||||
|
cookie.Expired = true;
|
||||||
|
res.Add (cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wssv.AddWebSocketService<Chat> (
|
||||||
|
"/Chat",
|
||||||
|
() => new Chat ("Anon#") {
|
||||||
|
Protocol = "chat",
|
||||||
|
OriginValidator = value => {
|
||||||
|
Uri origin;
|
||||||
|
return !value.IsNullOrEmpty () &&
|
||||||
|
Uri.TryCreate (value, UriKind.Absolute, out origin) &&
|
||||||
|
origin.Host == "localhost";
|
||||||
|
},
|
||||||
|
CookiesValidator = (req, res) => {
|
||||||
|
foreach (Cookie cookie in req) {
|
||||||
|
cookie.Expired = true;
|
||||||
|
res.Add (cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
wssv.Start ();
|
wssv.Start ();
|
||||||
if (wssv.IsListening) {
|
if (wssv.IsListening) {
|
||||||
|
@ -45,9 +45,48 @@ namespace Example3
|
|||||||
|
|
||||||
_httpsv.AddWebSocketService<Echo> ("/Echo");
|
_httpsv.AddWebSocketService<Echo> ("/Echo");
|
||||||
_httpsv.AddWebSocketService<Chat> ("/Chat");
|
_httpsv.AddWebSocketService<Chat> ("/Chat");
|
||||||
//_httpsv.AddWebSocketService<Chat> (
|
|
||||||
// "/Chat",
|
/* With initializing
|
||||||
// () => new Chat ("Anon#") { Protocol = "chat" });
|
_httpsv.AddWebSocketService<Echo> (
|
||||||
|
"/Echo",
|
||||||
|
() => new Echo () {
|
||||||
|
Protocol = "echo",
|
||||||
|
OriginValidator = value => {
|
||||||
|
Uri origin;
|
||||||
|
return !value.IsNullOrEmpty () &&
|
||||||
|
Uri.TryCreate (value, UriKind.Absolute, out origin) &&
|
||||||
|
origin.Host == "localhost";
|
||||||
|
},
|
||||||
|
CookiesValidator = (req, res) => {
|
||||||
|
foreach (Cookie cookie in req) {
|
||||||
|
cookie.Expired = true;
|
||||||
|
res.Add (cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_httpsv.AddWebSocketService<Chat> (
|
||||||
|
"/Chat",
|
||||||
|
() => new Chat ("Anon#") {
|
||||||
|
Protocol = "chat",
|
||||||
|
OriginValidator = value => {
|
||||||
|
Uri origin;
|
||||||
|
return !value.IsNullOrEmpty () &&
|
||||||
|
Uri.TryCreate (value, UriKind.Absolute, out origin) &&
|
||||||
|
origin.Host == "localhost";
|
||||||
|
},
|
||||||
|
CookiesValidator = (req, res) => {
|
||||||
|
foreach (Cookie cookie in req) {
|
||||||
|
cookie.Expired = true;
|
||||||
|
res.Add (cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
_httpsv.Start ();
|
_httpsv.Start ();
|
||||||
if (_httpsv.IsListening) {
|
if (_httpsv.IsListening) {
|
||||||
|
@ -45,6 +45,9 @@ namespace WebSocketSharp.Server
|
|||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private WebSocketContext _context;
|
private WebSocketContext _context;
|
||||||
|
private Func<CookieCollection, CookieCollection, bool>
|
||||||
|
_cookiesValidator;
|
||||||
|
private Func<string, bool> _originValidator;
|
||||||
private string _protocol;
|
private string _protocol;
|
||||||
private WebSocketSessionManager _sessions;
|
private WebSocketSessionManager _sessions;
|
||||||
private DateTime _start;
|
private DateTime _start;
|
||||||
@ -115,6 +118,38 @@ namespace WebSocketSharp.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the delegate called to validate the HTTP cookies included in the WebSocket
|
||||||
|
/// connection request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The delegate is called when the <see cref="WebSocket"/> used in the current session
|
||||||
|
/// validates the WebSocket connection request.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>
|
||||||
|
/// <para>
|
||||||
|
/// A <c>Func<CookieCollection, CookieCollection, bool></c> delegate that references
|
||||||
|
/// the method(s) used to validate the cookies. 1st <see cref="CookieCollection"/> passed to
|
||||||
|
/// this delegate contains the cookies to validate, if any. 2nd <see cref="CookieCollection"/>
|
||||||
|
/// passed to this delegate receives the cookies to send to the client.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// This delegate should return <c>true</c> if the cookies are valid; otherwise, <c>false</c>.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The default value is <see langword="null"/>, and it does nothing to validate.
|
||||||
|
/// </para>
|
||||||
|
/// </value>
|
||||||
|
public Func<CookieCollection, CookieCollection, bool> CookiesValidator {
|
||||||
|
get {
|
||||||
|
return _cookiesValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
set {
|
||||||
|
_cookiesValidator = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the unique ID of the current session.
|
/// Gets the unique ID of the current session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -125,6 +160,38 @@ namespace WebSocketSharp.Server
|
|||||||
get; private set;
|
get; private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the delegate called to validate the Origin header included in the WebSocket
|
||||||
|
/// connection request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The delegate is called when the <see cref="WebSocket"/> used in the current session
|
||||||
|
/// validates the WebSocket connection request.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>
|
||||||
|
/// <para>
|
||||||
|
/// A <c>Func<string, bool></c> delegate that references the method(s) used to validate
|
||||||
|
/// the origin header. A <see cref="string"/> passed to this delegate represents the value of
|
||||||
|
/// the origin header to validate, if any.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// This delegate should return <c>true</c> if the origin header is valid; otherwise,
|
||||||
|
/// <c>false</c>.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The default value is <see langword="null"/>, and it does nothing to validate.
|
||||||
|
/// </para>
|
||||||
|
/// </value>
|
||||||
|
public Func<string, bool> OriginValidator {
|
||||||
|
get {
|
||||||
|
return _originValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
set {
|
||||||
|
_originValidator = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the subprotocol of the <see cref="WebSocket"/> used in the current session.
|
/// Gets or sets the subprotocol of the <see cref="WebSocket"/> used in the current session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -192,6 +259,16 @@ namespace WebSocketSharp.Server
|
|||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
|
private string checkIfValidConnectionRequest (WebSocketContext context)
|
||||||
|
{
|
||||||
|
return _originValidator != null && !_originValidator (context.Origin)
|
||||||
|
? "Invalid Origin header."
|
||||||
|
: _cookiesValidator != null &&
|
||||||
|
!_cookiesValidator (context.CookieCollection, context.WebSocket.CookieCollection)
|
||||||
|
? "Invalid Cookies."
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
private void onClose (object sender, CloseEventArgs e)
|
private void onClose (object sender, CloseEventArgs e)
|
||||||
{
|
{
|
||||||
if (ID == null)
|
if (ID == null)
|
||||||
@ -234,7 +311,7 @@ namespace WebSocketSharp.Server
|
|||||||
|
|
||||||
_websocket = context.WebSocket;
|
_websocket = context.WebSocket;
|
||||||
_websocket.Protocol = _protocol;
|
_websocket.Protocol = _protocol;
|
||||||
_websocket.CookiesValidation = ValidateCookies;
|
_websocket.CustomHandshakeRequestChecker = checkIfValidConnectionRequest;
|
||||||
|
|
||||||
_websocket.OnOpen += onOpen;
|
_websocket.OnOpen += onOpen;
|
||||||
_websocket.OnMessage += onMessage;
|
_websocket.OnMessage += onMessage;
|
||||||
@ -422,28 +499,6 @@ namespace WebSocketSharp.Server
|
|||||||
_websocket.SendAsync (stream, length, completed);
|
_websocket.SendAsync (stream, length, completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used to validate the HTTP cookies included in the WebSocket connection request.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This method is called when the <see cref="WebSocket"/> used in the current session
|
|
||||||
/// validates the WebSocket connection request.
|
|
||||||
/// </remarks>
|
|
||||||
/// <returns>
|
|
||||||
/// <c>true</c> if the cookies are valid; otherwise, <c>false</c>. This method returns
|
|
||||||
/// <c>true</c> as default.
|
|
||||||
/// </returns>
|
|
||||||
/// <param name="request">
|
|
||||||
/// A <see cref="CookieCollection"/> that contains the cookies to validate.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="response">
|
|
||||||
/// A <see cref="CookieCollection"/> that receives the cookies to send to the client.
|
|
||||||
/// </param>
|
|
||||||
protected virtual bool ValidateCookies (CookieCollection request, CookieCollection response)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,13 +75,13 @@ namespace WebSocketSharp
|
|||||||
private CompressionMethod _compression;
|
private CompressionMethod _compression;
|
||||||
private WebSocketContext _context;
|
private WebSocketContext _context;
|
||||||
private CookieCollection _cookies;
|
private CookieCollection _cookies;
|
||||||
private Func<CookieCollection, CookieCollection, bool>
|
|
||||||
_cookiesValidation;
|
|
||||||
private NetworkCredential _credentials;
|
private NetworkCredential _credentials;
|
||||||
private string _extensions;
|
private string _extensions;
|
||||||
private AutoResetEvent _exitReceiving;
|
private AutoResetEvent _exitReceiving;
|
||||||
private object _forConn;
|
private object _forConn;
|
||||||
private object _forSend;
|
private object _forSend;
|
||||||
|
private Func<WebSocketContext, string>
|
||||||
|
_handshakeRequestChecker;
|
||||||
private volatile Logger _logger;
|
private volatile Logger _logger;
|
||||||
private uint _nonceCount;
|
private uint _nonceCount;
|
||||||
private string _origin;
|
private string _origin;
|
||||||
@ -192,13 +192,20 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#region Internal Properties
|
#region Internal Properties
|
||||||
|
|
||||||
internal Func<CookieCollection, CookieCollection, bool> CookiesValidation {
|
internal CookieCollection CookieCollection {
|
||||||
get {
|
get {
|
||||||
return _cookiesValidation;
|
return _cookies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// As server
|
||||||
|
internal Func<WebSocketContext, string> CustomHandshakeRequestChecker {
|
||||||
|
get {
|
||||||
|
return _handshakeRequestChecker ?? (context => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
_cookiesValidation = value;
|
_handshakeRequestChecker = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,9 +692,7 @@ namespace WebSocketSharp
|
|||||||
? "Invalid Sec-WebSocket-Key header."
|
? "Invalid Sec-WebSocket-Key header."
|
||||||
: !validateSecWebSocketVersionClientHeader (headers ["Sec-WebSocket-Version"])
|
: !validateSecWebSocketVersionClientHeader (headers ["Sec-WebSocket-Version"])
|
||||||
? "Invalid Sec-WebSocket-Version header."
|
? "Invalid Sec-WebSocket-Version header."
|
||||||
: !validateCookies (context.CookieCollection, _cookies)
|
: CustomHandshakeRequestChecker (context);
|
||||||
? "Invalid Cookies."
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// As client
|
// As client
|
||||||
@ -1258,14 +1263,6 @@ namespace WebSocketSharp
|
|||||||
receive ();
|
receive ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// As server
|
|
||||||
private bool validateCookies (CookieCollection request, CookieCollection response)
|
|
||||||
{
|
|
||||||
return _cookiesValidation != null
|
|
||||||
? _cookiesValidation (request, response)
|
|
||||||
: true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// As server
|
// As server
|
||||||
private bool validateHostHeader (string value)
|
private bool validateHostHeader (string value)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user