If you are still using an ASP.NET SOAP web service then the easiest way that fits your requirements IMO is to use the ASP.NET Forms authentication with a Membership DB. If you are starting out fresh I'd recommend going with WCF - if you can't/or won't do that this post applies to the "classic" ASP.NET SOAP web services.
To add Forms authentication to a web service:
Configure it just like you would for any other web site but set it to allow access for everyone:
<authorization>
<allow users="*"/>
</authorization>
Implement Login/Logout methods and issue the authentication ticket in the Login method. Further requests to the web service then can use the issued authentication ticket.
All other web methods you want to protect you can then decorate with
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
These methods will now throw a Security exception if a client is not authenticated.
Example for a protected method:
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
[WebMethod(Description = "Your protected method")]
public string Foo()
{
return "bar";
}
Example for Login method:
[WebMethod(Description = "Login to start a session")]
public bool Login(string userName, string password)
{
if (!Membership.Provider.ValidateUser(userName, password))
return false;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.AddMinutes(500),
false,
FormsAuthentication.FormsCookiePath);// Path cookie valid for
// Encrypt the cookie using the machine key for secure transport
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, // Name of auth cookie
hash); // Hashed ticket
// Set the cookie's expiration time to the tickets expiration time
if (ticket.IsPersistent)
cookie.Expires = ticket.Expiration;
// Add the cookie to the list for outgoing response
if(HttpContext.Current !=null)
HttpContext.Current.Response.Cookies.Add(cookie);
FormsAuthentication.SetAuthCookie(userName, true);
return true;
}