Modified HTTP auth for HttpListener class

This commit is contained in:
sta 2014-11-21 15:07:25 +09:00
parent 55527ef514
commit b521456dd6
3 changed files with 74 additions and 70 deletions

View File

@ -38,6 +38,7 @@
#endregion #endregion
using System; using System;
using System.Security.Principal;
using System.Threading; using System.Threading;
namespace WebSocketSharp.Net namespace WebSocketSharp.Net
@ -114,42 +115,31 @@ namespace WebSocketSharp.Net
if (schm == AuthenticationSchemes.Anonymous) if (schm == AuthenticationSchemes.Anonymous)
return true; return true;
var req = context.Request; if (schm == AuthenticationSchemes.None) {
var authRes = req.Headers["Authorization"];
if (schm == AuthenticationSchemes.Basic) {
if (authRes == null || !authRes.StartsWith ("basic", StringComparison.OrdinalIgnoreCase)) {
context.Response.CloseWithAuthChallenge (
AuthenticationChallenge.CreateBasicChallenge (listener.Realm).ToBasicString ());
return false;
}
}
else if (schm == AuthenticationSchemes.Digest) {
if (authRes == null || !authRes.StartsWith ("digest", StringComparison.OrdinalIgnoreCase)) {
context.Response.CloseWithAuthChallenge (
AuthenticationChallenge.CreateDigestChallenge (listener.Realm).ToDigestString ());
return false;
}
}
else {
context.Response.Close (HttpStatusCode.Forbidden); context.Response.Close (HttpStatusCode.Forbidden);
return false; return false;
} }
var req = context.Request;
var realm = listener.Realm; var realm = listener.Realm;
context.SetUser (authRes, schm, realm, listener.UserCredentialsFinder); var user = createUser (
if (req.IsAuthenticated) req.Headers["Authorization"], schm, realm, req.HttpMethod, listener.UserCredentialsFinder);
if (user != null && user.Identity.IsAuthenticated) {
context.User = user;
req.IsAuthenticated = true;
return true; return true;
}
if (schm == AuthenticationSchemes.Basic) if (schm == AuthenticationSchemes.Basic)
context.Response.CloseWithAuthChallenge ( context.Response.CloseWithAuthChallenge (
AuthenticationChallenge.CreateBasicChallenge (realm).ToBasicString ()); AuthenticationChallenge.CreateBasicChallenge (realm).ToBasicString ());
else if (schm == AuthenticationSchemes.Digest)
if (schm == AuthenticationSchemes.Digest)
context.Response.CloseWithAuthChallenge ( context.Response.CloseWithAuthChallenge (
AuthenticationChallenge.CreateDigestChallenge (realm).ToDigestString ()); AuthenticationChallenge.CreateDigestChallenge (realm).ToDigestString ());
else
context.Response.Close (HttpStatusCode.Forbidden);
return false; return false;
} }
@ -175,6 +165,46 @@ 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

@ -57,18 +57,13 @@ namespace WebSocketSharp.Net
private HttpConnection _connection; private HttpConnection _connection;
private string _error; private string _error;
private int _errorStatus; private int _errorStatus;
private HttpListener _listener;
private HttpListenerRequest _request; private HttpListenerRequest _request;
private HttpListenerResponse _response; private HttpListenerResponse _response;
private IPrincipal _user; private IPrincipal _user;
#endregion #endregion
#region Internal Fields
internal HttpListener Listener;
#endregion
#region Internal Constructors #region Internal Constructors
internal HttpListenerContext (HttpConnection connection) internal HttpListenerContext (HttpConnection connection)
@ -115,6 +110,16 @@ namespace WebSocketSharp.Net
} }
} }
internal HttpListener Listener {
get {
return _listener;
}
set {
_listener = value;
}
}
#endregion #endregion
#region Public Properties #region Public Properties
@ -147,51 +152,16 @@ namespace WebSocketSharp.Net
/// 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 IPrincipal User { public IPrincipal User {
get { get {
return _user; return _user;
} }
internal set {
_user = value;
} }
#endregion
#region Internal Methods
internal void SetUser (
string response,
AuthenticationSchemes scheme,
string realm,
Func<IIdentity, NetworkCredential> credentialsFinder)
{
var res = AuthenticationResponse.Parse (response);
if (res == null)
return;
var id = res.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

@ -59,6 +59,7 @@ namespace WebSocketSharp.Net
private static readonly byte[] _100continue; private static readonly byte[] _100continue;
private string[] _acceptTypes; private string[] _acceptTypes;
private bool _authenticated;
private bool _chunked; private bool _chunked;
private Encoding _contentEncoding; private Encoding _contentEncoding;
private long _contentLength; private long _contentLength;
@ -241,8 +242,11 @@ namespace WebSocketSharp.Net
/// </value> /// </value>
public bool IsAuthenticated { public bool IsAuthenticated {
get { get {
var user = _context.User; return _authenticated;
return user != null && user.Identity.IsAuthenticated; }
internal set {
_authenticated = value;
} }
} }