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

View File

@ -57,18 +57,13 @@ namespace WebSocketSharp.Net
private HttpConnection _connection;
private string _error;
private int _errorStatus;
private HttpListener _listener;
private HttpListenerRequest _request;
private HttpListenerResponse _response;
private IPrincipal _user;
#endregion
#region Internal Fields
internal HttpListener Listener;
#endregion
#region Internal Constructors
internal HttpListenerContext (HttpConnection connection)
@ -115,6 +110,16 @@ namespace WebSocketSharp.Net
}
}
internal HttpListener Listener {
get {
return _listener;
}
set {
_listener = value;
}
}
#endregion
#region Public Properties
@ -147,51 +152,16 @@ namespace WebSocketSharp.Net
/// Gets the client information (identity, authentication, and security roles).
/// </summary>
/// <value>
/// A <see cref="IPrincipal"/> that represents the client information.
/// A <see cref="IPrincipal"/> instance that represents the client information.
/// </value>
public IPrincipal User {
get {
return _user;
}
}
#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);
internal set {
_user = value;
}
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

View File

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