Modified HTTP auth for WebSocketServer class

This commit is contained in:
sta 2014-11-22 14:46:42 +09:00
parent b521456dd6
commit 533ef2090a
4 changed files with 68 additions and 93 deletions

View File

@ -122,7 +122,7 @@ namespace WebSocketSharp.Net
var req = context.Request; var req = context.Request;
var realm = listener.Realm; var realm = listener.Realm;
var user = createUser ( var user = HttpUtility.CreateUser (
req.Headers["Authorization"], schm, realm, req.HttpMethod, listener.UserCredentialsFinder); req.Headers["Authorization"], schm, realm, req.HttpMethod, listener.UserCredentialsFinder);
if (user != null && user.Identity.IsAuthenticated) { if (user != null && user.Identity.IsAuthenticated) {
@ -165,46 +165,6 @@ namespace WebSocketSharp.Net
null); null);
} }
private static IPrincipal createUser (
string response,
AuthenticationSchemes scheme,
string realm,
string method,
Func<IIdentity, NetworkCredential> credentialsFinder)
{
if (response == null ||
!response.StartsWith (scheme.ToString (), StringComparison.OrdinalIgnoreCase))
return null;
var res = AuthenticationResponse.Parse (response);
if (res == null)
return null;
var id = res.ToIdentity ();
if (id == null)
return null;
NetworkCredential cred = null;
try {
cred = credentialsFinder (id);
}
catch {
}
if (cred == null)
return null;
var valid = scheme == AuthenticationSchemes.Basic
? ((HttpBasicIdentity) id).Password == cred.Password
: scheme == AuthenticationSchemes.Digest
? ((HttpDigestIdentity) id).IsValid (cred.Password, realm, method, null)
: false;
return valid
? new GenericPrincipal (id, cred.Roles)
: null;
}
#endregion #endregion
#region Internal Methods #region Internal Methods

View File

@ -46,6 +46,7 @@ using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Security.Principal;
using System.Text; using System.Text;
namespace WebSocketSharp.Net namespace WebSocketSharp.Net
@ -548,6 +549,46 @@ namespace WebSocketSharp.Net
return res; return res;
} }
internal static IPrincipal CreateUser (
string response,
AuthenticationSchemes scheme,
string realm,
string method,
Func<IIdentity, NetworkCredential> credentialsFinder)
{
if (response == null ||
!response.StartsWith (scheme.ToString (), StringComparison.OrdinalIgnoreCase))
return null;
var res = AuthenticationResponse.Parse (response);
if (res == null)
return null;
var id = res.ToIdentity ();
if (id == null)
return null;
NetworkCredential cred = null;
try {
cred = credentialsFinder (id);
}
catch {
}
if (cred == null)
return null;
var valid = scheme == AuthenticationSchemes.Basic
? ((HttpBasicIdentity) id).Password == cred.Password
: scheme == AuthenticationSchemes.Digest
? ((HttpDigestIdentity) id).IsValid (cred.Password, realm, method, null)
: false;
return valid
? new GenericPrincipal (id, cred.Roles)
: null;
}
internal static Encoding GetEncoding (string contentType) internal static Encoding GetEncoding (string contentType)
{ {
var parts = contentType.Split (';'); var parts = contentType.Split (';');

View File

@ -105,6 +105,12 @@ namespace WebSocketSharp.Net.WebSockets
#region Internal Properties #region Internal Properties
internal string HttpMethod {
get {
return _request.HttpMethod;
}
}
internal Stream Stream { internal Stream Stream {
get { get {
return _stream; return _stream;
@ -159,7 +165,7 @@ namespace WebSocketSharp.Net.WebSockets
/// </value> /// </value>
public override bool IsAuthenticated { public override bool IsAuthenticated {
get { get {
return _user != null && _user.Identity.IsAuthenticated; return _user != null;
} }
} }
@ -304,7 +310,7 @@ namespace WebSocketSharp.Net.WebSockets
/// Gets the client information (identity, authentication, and security roles). /// Gets the client information (identity, authentication, and security roles).
/// </summary> /// </summary>
/// <value> /// <value>
/// A <see cref="IPrincipal"/> that represents the client information. /// A <see cref="IPrincipal"/> instance that represents the client information.
/// </value> /// </value>
public override IPrincipal User { public override IPrincipal User {
get { get {
@ -359,38 +365,9 @@ namespace WebSocketSharp.Net.WebSockets
_request = HttpRequest.Read (_stream, 15000); _request = HttpRequest.Read (_stream, 15000);
} }
internal void SetUser ( internal void SetUser (IPrincipal value)
AuthenticationSchemes scheme,
string realm,
Func<IIdentity, NetworkCredential> credentialsFinder)
{ {
var authRes = _request.AuthenticationResponse; _user = value;
if (authRes == null)
return;
var id = authRes.ToIdentity ();
if (id == null)
return;
NetworkCredential cred = null;
try {
cred = credentialsFinder (id);
}
catch {
}
if (cred == null)
return;
var valid = scheme == AuthenticationSchemes.Basic
? ((HttpBasicIdentity) id).Password == cred.Password
: scheme == AuthenticationSchemes.Digest
? ((HttpDigestIdentity) id).IsValid (
cred.Password, realm, _request.HttpMethod, null)
: false;
if (valid)
_user = new GenericPrincipal (id, cred.Roles);
} }
#endregion #endregion

View File

@ -543,13 +543,16 @@ namespace WebSocketSharp.Server
_state = ServerState.Stop; _state = ServerState.Stop;
} }
private bool authenticateRequest ( private static bool authenticate (
AuthenticationSchemes scheme, TcpListenerWebSocketContext context) TcpListenerWebSocketContext context,
AuthenticationSchemes scheme,
string realm,
Func<IIdentity, NetworkCredential> credentialsFinder)
{ {
var chal = scheme == AuthenticationSchemes.Basic var chal = scheme == AuthenticationSchemes.Basic
? AuthenticationChallenge.CreateBasicChallenge (Realm).ToBasicString () ? AuthenticationChallenge.CreateBasicChallenge (realm).ToBasicString ()
: scheme == AuthenticationSchemes.Digest : scheme == AuthenticationSchemes.Digest
? AuthenticationChallenge.CreateDigestChallenge (Realm).ToDigestString () ? AuthenticationChallenge.CreateDigestChallenge (realm).ToDigestString ()
: null; : null;
if (chal == null) { if (chal == null) {
@ -558,9 +561,6 @@ namespace WebSocketSharp.Server
} }
var retry = -1; var retry = -1;
var schm = scheme.ToString ();
var realm = Realm;
var credFinder = UserCredentialsFinder;
Func<bool> auth = null; Func<bool> auth = null;
auth = () => { auth = () => {
retry++; retry++;
@ -569,19 +569,16 @@ namespace WebSocketSharp.Server
return false; return false;
} }
var res = context.Headers["Authorization"]; var user = HttpUtility.CreateUser (
if (res == null || !res.StartsWith (schm, StringComparison.OrdinalIgnoreCase)) { context.Headers["Authorization"], scheme, realm, context.HttpMethod, credentialsFinder);
context.SendAuthenticationChallenge (chal);
return auth ();
}
context.SetUser (scheme, realm, credFinder);
if (!context.IsAuthenticated) {
context.SendAuthenticationChallenge (chal);
return auth ();
}
if (user != null && user.Identity.IsAuthenticated) {
context.SetUser (user);
return true; return true;
}
context.SendAuthenticationChallenge (chal);
return auth ();
}; };
return auth (); return auth ();
@ -642,7 +639,7 @@ namespace WebSocketSharp.Server
try { try {
var ctx = cl.GetWebSocketContext (null, _secure, _sslConfig, _logger); var ctx = cl.GetWebSocketContext (null, _secure, _sslConfig, _logger);
if (_authSchemes != AuthenticationSchemes.Anonymous && if (_authSchemes != AuthenticationSchemes.Anonymous &&
!authenticateRequest (_authSchemes, ctx)) !authenticate (ctx, _authSchemes, Realm, UserCredentialsFinder))
return; return;
processWebSocketRequest (ctx); processWebSocketRequest (ctx);