Custom HTTP Basic Authentication for ASP.NET Web S

2019-02-01 02:38发布

问题:

I am refactoring a working ASP.NET Web Application to expose Web Services interface using ASP.NET Web Service. According to Web Services authentication - best practices, Basic Auth over https is the way to go. Let's assume it is, as opposed to doing WS-Security, X509, etc..

On .NET 3.5/VS 2008, what's the simplest way of implementing custom http Basic Authentication (non-Windows account), for example, accepting only if user name is "foo" and password is "bar". Ultimately, I'd like Thread.CurrentPrincipal set.

Do I write my own HttpModule or can this be done simpler?

回答1:

Likely using Custom Basic Authentication for IIS, written by Dominick Baier is the way to go. As he points out WCF 3.5's usernames over transport security cannot be used on IIS-hosted service, although my question was regarding ASP.NET Web Services not WCF.

There's another implementation of HTTP Module called Basic authentication in ASP.NET against custom datasource by Santosh Sahoo.

Although it's not what I wanted, I found QuickStart Tutorial's SOAP Headers sample to be informative workaround. Sending password in plain text over http is clearly insecure, but this example could be extended to add more security, for instance running on https or sending hash of "password + one-time GUID + timestamp".



回答2:

Grab the value of the Authorization header, parse it and validate the username/password.

The value is username:password, encoded as a Base64 string.

See http://en.wikipedia.org/wiki/Basic_access_authentication for details.

Edit: if you want this done for every request, using the custom auth scheme, then it would be easier to write an HttpModule to handle parsing the header and setting the thread's principal.



回答3:

If you are considering WCF, you can use usernameOverTransport security for basicHttpBinding. i.e. username and passowrd reside in the SOAP header of the request and all the traffic are protected by SSL encryption over the wire.

A custom UserNamePasswordValidator validator can be used to authenticate the incoming credentials against e.g. database.

You can set the thread principal within a custom IAuthorizationPolicy in the service behavior.

e.g. Evaluate method implementation for IAuthorizationPolicy for setting current principal

public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
       Object obj;
       if( evaluationContext.Properties.TryGetValue( "Identities", out obj ))
       {
            // get the authenticated identity
            IIdentity client = (obj as IList<IIdentity>)[0];
            evaluationContext.Properties["Principal"] = ... // create principal obj here for the identity
            // this will set thread's current principal
       }
       return true;
}