|
The Custom SOAP Extension Implementation
Listing 1. This code shows the SOAP extension implementation that enforces the role-based security policy based on the caller credentials in the WS-Security message header. /// <summary>
/// The SOAP extension implementation
/// that provides role-based
/// security information
/// from the WS-Security message header.
/// </summary>
public class AuthorizedRolesExtension
: SoapExtension
{
private string[] roles = null;
private string roleString = null;
private string methodName = null;
/// <summary>
/// The method that processes the
/// SOAP message and looks
/// for the WS-Security User token.
/// </summary>
/// <param name="message">The SOAP message</param>
public override void ProcessMessage (SoapMessage message)
{
if (message.Stage == SoapMessageStage.AfterDeserialize)
{
SoapContext ctxt =
RequestSoapContext.Current;
foreach (SecurityToken tok
in ctxt.Security.Tokens)
{
// Only interested in
// user name tokens for
// this sample implementation.
if (tok is UsernameToken)
{
UsernameToken user =
(UsernameToken)tok;
// See the comments on the
// GetRoles method.
string[] userRoles =
GetRoles(user.Username);
bool isAuthorized = false;
// Allow anonymous and all
// access levels through.
if(roles.Length == 1
&& (roles[0].Equals("*")
|| roles[0].Equals("?")))
{
isAuthorized = true;
}
else
{
// Match the roles.
foreach (string role
in roles)
{
foreach(string userRole
in userRoles)
{
if(role.Equals(userRole))
{
isAuthorized = true;
break;
}
}
if(isAuthorized)
break;
}
}
// Still not authorized.
if(!isAuthorized)
{
throw new SoapException(
"Unauthorized Access to "
+ methodName
+ " by "
+ user.Username,
SoapException.ClientFaultCode);
}
GenericIdentity id =
new GenericIdentity(
user.Username);
GenericPrincipal p =
new GenericPrincipal(
id,userRoles);
HttpContext.Current.User = p;
return;
}
}
// No user token.
// Check to see
// if anonymous access
// is allowed.
if(roles.Length == 1
&& roles[0].Equals("?"))
{
return;
}
// End of method.
// Not authorized.
throw new SoapException(
"Unauthorized [Anonymous] Access to "
+ methodName,
SoapException.ClientFaultCode);
}
}
/// <summary>
/// Returns an array of roles permitted
/// for the given user.
/// Override this method in your implementation
/// to do something more "real-world."
/// </summary>
/// <param name="username">
/// the username to get the roles for
/// </param>
/// <returns>an array of roles</returns>
protected virtual string[] GetRoles(
string username)
{
if(username.Equals("Bob"))
return new string[]{"Guest"};
else if(username.Equals("Cathy"))
return new string[]{"Manager"};
else
return new string[0];
}
/// <summary>
/// This method is not implemented
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public override Object GetInitializer (
Type type)
{
return GetType ();
}
/// <summary>
/// Iniitializes the SOAP Extension
/// </summary>
/// <param name="info"></param>
/// <param name="attribute"></param>
/// <returns></returns>
public override Object GetInitializer (
LogicalMethodInfo info,
SoapExtensionAttribute attribute)
{
return new InitObject(info,attribute);
}
/// <summary>
/// Iniitializes the SOAP Extension
/// </summary>
/// <param name="initializer"></param>
public override void Initialize (
Object initializer)
{
InitObject o =
initializer as InitObject;
if(o != null)
{
roleString =
((AuthorizedRolesAttribute)o.attr).Roles;
roles = roleString.Split(',');
string assemblyName =
o.methodInfo.MethodInfo.DeclaringType.ToString();
assemblyName =
assemblyName.Substring(assemblyName.LastIndexOf(".")+1);
methodName =
assemblyName + "::" + o.methodInfo.MethodInfo.Name;
}
}
}
class InitObject
{
public LogicalMethodInfo methodInfo;
public SoapExtensionAttribute attr;
public InitObject(
LogicalMethodInfo methodInfo,
SoapExtensionAttribute attr)
{
this.methodInfo = methodInfo;
this.attr = attr;
}
}
|