Modified cookies validation, and added origin header validation

This commit is contained in:
sta 2014-03-07 21:15:55 +09:00
parent 12efc99805
commit 048627b4f9
5 changed files with 175 additions and 56 deletions

View File

@ -16,16 +16,5 @@ namespace Example2
Send (msg);
}
protected override bool ValidateCookies (
CookieCollection request, CookieCollection response)
{
foreach (Cookie cookie in request) {
cookie.Expired = true;
response.Add (cookie);
}
return true;
}
}
}

View File

@ -41,9 +41,48 @@ namespace Example2
wssv.AddWebSocketService<Echo> ("/Echo");
wssv.AddWebSocketService<Chat> ("/Chat");
//wssv.AddWebSocketService<Chat> (
// "/Chat",
// () => new Chat ("Anon#") { Protocol = "chat" });
/* With initializing
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 ();
if (wssv.IsListening) {

View File

@ -45,9 +45,48 @@ namespace Example3
_httpsv.AddWebSocketService<Echo> ("/Echo");
_httpsv.AddWebSocketService<Chat> ("/Chat");
//_httpsv.AddWebSocketService<Chat> (
// "/Chat",
// () => new Chat ("Anon#") { Protocol = "chat" });
/* With initializing
_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 ();
if (_httpsv.IsListening) {

View File

@ -45,6 +45,9 @@ namespace WebSocketSharp.Server
#region Private Fields
private WebSocketContext _context;
private Func<CookieCollection, CookieCollection, bool>
_cookiesValidator;
private Func<string, bool> _originValidator;
private string _protocol;
private WebSocketSessionManager _sessions;
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&lt;CookieCollection, CookieCollection, bool&gt;</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>
/// Gets the unique ID of the current session.
/// </summary>
@ -125,6 +160,38 @@ namespace WebSocketSharp.Server
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&lt;string, bool&gt;</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>
/// Gets or sets the subprotocol of the <see cref="WebSocket"/> used in the current session.
/// </summary>
@ -192,6 +259,16 @@ namespace WebSocketSharp.Server
#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)
{
if (ID == null)
@ -234,7 +311,7 @@ namespace WebSocketSharp.Server
_websocket = context.WebSocket;
_websocket.Protocol = _protocol;
_websocket.CookiesValidation = ValidateCookies;
_websocket.CustomHandshakeRequestChecker = checkIfValidConnectionRequest;
_websocket.OnOpen += onOpen;
_websocket.OnMessage += onMessage;
@ -422,28 +499,6 @@ namespace WebSocketSharp.Server
_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
}
}

View File

@ -75,13 +75,13 @@ namespace WebSocketSharp
private CompressionMethod _compression;
private WebSocketContext _context;
private CookieCollection _cookies;
private Func<CookieCollection, CookieCollection, bool>
_cookiesValidation;
private NetworkCredential _credentials;
private string _extensions;
private AutoResetEvent _exitReceiving;
private object _forConn;
private object _forSend;
private Func<WebSocketContext, string>
_handshakeRequestChecker;
private volatile Logger _logger;
private uint _nonceCount;
private string _origin;
@ -192,13 +192,20 @@ namespace WebSocketSharp
#region Internal Properties
internal Func<CookieCollection, CookieCollection, bool> CookiesValidation {
internal CookieCollection CookieCollection {
get {
return _cookiesValidation;
return _cookies;
}
}
// As server
internal Func<WebSocketContext, string> CustomHandshakeRequestChecker {
get {
return _handshakeRequestChecker ?? (context => null);
}
set {
_cookiesValidation = value;
_handshakeRequestChecker = value;
}
}
@ -685,9 +692,7 @@ namespace WebSocketSharp
? "Invalid Sec-WebSocket-Key header."
: !validateSecWebSocketVersionClientHeader (headers ["Sec-WebSocket-Version"])
? "Invalid Sec-WebSocket-Version header."
: !validateCookies (context.CookieCollection, _cookies)
? "Invalid Cookies."
: null;
: CustomHandshakeRequestChecker (context);
}
// As client
@ -1258,14 +1263,6 @@ namespace WebSocketSharp
receive ();
}
// As server
private bool validateCookies (CookieCollection request, CookieCollection response)
{
return _cookiesValidation != null
? _cookiesValidation (request, response)
: true;
}
// As server
private bool validateHostHeader (string value)
{