Modified HTTP auth for WebSocketServer class
This commit is contained in:
parent
b521456dd6
commit
533ef2090a
@ -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
|
||||||
|
@ -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 (';');
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user