问题
I have a self-hosted REST app running cross platform on mono/.NET. The one problem is that HttpListener manages and blocks manual setting of the WWW-Authenticate header. Which is fine if you limit yourself to the built-in Basic, NTLM, etc authentication, or don't need authentication, but is a problem if you want to accept any other kind of tokens.
I am using JWT tokens with a REST style interface, using Basic[1] auth for the initial authentication. In another part of the app, I am doing something similar but using custom tokens and/or Basic auth as a fallback in another part of the API.
The question:
How can I get HttpListener to send the "WWW-Authenticate: Basic" challenge header while also allowing non-Basic Authorization tokens through?
I have tried setting both Basic and Anonymous in the listener thusly:
_listener.AuthenticationSchemes =
AuthenticationSchemes.Basic | AuthenticationSchemes.Anonymous;
This results in no WWW-Authenticate header being returned under any circumstances. I believe this is supposed to allow either Basic or unauthenticated connections, and should also set the WWW-Authenticate challenge when I set the status code to 401 (HttpStatusCode.Unauthorized). But it does not (on either mono or .NET).
If I only set AuthenticationSchemes.Basic, HttpListener refuses all connections without a Basic style token, which is not remotely useful.
Obvious but lame workaround:
Currently I am simply violating the HTTP specification and returning 401 without a WWW-Authenticate header. This works, but reduces compatibility with third party tools.
I have considered using a completely different HttpListener implementation, although most seem to be either in the prototype stage or part of a large library of their own. I have considered writing my own HttpListener, but at that point porting the entire application to Java begins to look attractive. I would like to find recommendations that are less work than a complete platform port or writing my own library.
Ideas?
[1] - Basic auth is needed here for backward compatibility with low level scripts and some other systems. Please assume that I understand the security implications and am using SSL, etc.
回答1:
HttpListener simply won't work for any auth that is not built-in. Microsoft's implementation is very aggressive about restricting auth to the four built-in types, and that's that. For token based auth or any other purpose, you can't use System.Net.HttpListener.
My project is now using (a fork of) MediaBrowser/SocketHttpListener from github, which is a fork of mono-project's HttpListener. This has the added benefit that it does not use the .NET built-in HTTP support, so your app does not require admin access, but the disadvantage (or is it?) that you no longer have built-in-but-kind-of-a-pain-to-work-with HTTPS support from the framework. (I recommend using a proxy (apache or similar) for HTTPS in any case.)
Not sure whether I should accept my own answer here, but I honestly haven't found a better answer. Hope this helps somebody!
来源:https://stackoverflow.com/questions/33290559/httplistener-with-jwt-and-basic-auth-how-to-send-www-authenticate-self-hosted