
17 November 2007, 22:32 von
klaus_b3114 mal gelesen.Wie schon in einem vorherigen Post (Teil 2) angesprochen, will ich mich in diesem Eintrag mit der Überprüfung des übertragenen SOAP-Header befassen. Da ich diverse Webdienste mit jeweils mehreren Methoden verwende, wollte ich einen einfachen Weg um den SOAP-Header zu überprüfen ohne in den einzelnen Web Methoden all zuviel Code schreiben zu müssen. Als der einfachste Weg erschien es mir, einfach den gesamten SOAP-Header an eine statische Methode einer Klasse zu übergeben und das Ergebnis als bool auszuwerten. Wie schon im Post zu Teil 2 gezeigt geht es tatsächlich mit dem folgendem Konstrukt:
In der Methode IsHeaderValid der Klasse CheckAuthHeader wird zunächst die Eigenschaft IsEditMode überprüft und je nach Rückgabe, true oder false, an die passende Überladung der Methode IsVerified aus der Klasse AuthHeaderVerify übergeben. In dieser Klasse wird dann die eigentliche Überprüfung des SOAP-Header durchgeführt.
CheckAuthHeader.cs
public sealed class CheckAuthHeader
{
/// <summary>
/// Dummy-Konstruktor
/// </summary>
private CheckAuthHeader()
{
}
/// <summary>
/// Überprüft ob ein SoapAuthHeader gültig ist.
/// </summary>
/// <param name="authHeader">
/// Der zu überprüfende SoapAuthHeader
/// </param>
/// <returns>
/// <c>true</c> falls alles in Ordnung ist, anderenfalls <c>false</c>.
///</returns>
/// <remarks>n/a</remarks>
public static bool IsHeaderValid(SoapAuthHeader authHeader)
{
// autheader auf null prüfen
if (authHeader == null)
{
return false;
}
// prüfen ob EditMode aktiv
if (authHeader.IsEditMode)
{
// Überladung mit UserName
if (!AuthHeaderVerify.IsVerified(
authHeader.Created, authHeader.Expires,
authHeader.UserName, authHeader.IsEditMode,
authHeader.HashValue))
{
return false;
}
}
else
{
if (!AuthHeaderVerify.IsVerified(
authHeader.Created, authHeader.Expires,
authHeader.IsEditMode, authHeader.HashValue))
{
return false;
}
}
return true;
}
}Das folgende Listing zeigt die beiden Überladungen der Methode IsVerified sowie die benötigten privaten Methoden.
public sealed class AuthHeaderVerify
{
/// <summary>
/// Dummy-Konstruktor
/// </summary>
private AuthHeaderVerify()
{
}
#region Methods
#region public Methods
/// <summary>
/// Überprüft den AuthHeader auf seine Gültigkeit.
/// </summary>
/// <param name="created">Gibt an, wann das Objekt erzeugt wurde.</param>
/// <param name="expires">Gibt den Zeitraum der Gültigkeit des Objekts an.</param>
/// <param name="isEditMode">Gibt an, ob ein DataSet zum editieren geladen werden soll.</param>
/// <param name="hashValue">Der Hash-Wert der zu überprüfenden Objekte.</param>
/// <returns><c>true</c> falls der AuthHeader gültig und einwandfrei ist, anderenfalls <c>false</c>.</returns>
/// <remarks>n/a</remarks>
public static bool IsVerified(DateTime created, double expires, bool isEditMode, byte[] hashValue)
{
bool isVerified = false;
if (!isEditMode && isNotExpired(created, expires) &&
isHashValid(new object[] { created, expires, isEditMode }, hashValue))
{
isVerified = true;
}
return isVerified;
}
/// <summary>
/// Überprüft den AuthHeader auf seine Gültigkeit.
/// </summary>
/// <param name="created">Gibt an, wann das Objekt erzeugt wurde.</param>
/// <param name="expires">Gibt den Zeitraum der Gültigkeit des Objekts an.</param>
/// <param name="userName">Der Name des Benutzers, der im AuthHeader übermittelt wurde.</param>
/// <param name="isEditMode">Gibt an, ob ein DataSet zum editieren geladen werden soll.</param>
/// <param name="hashValue">Der Hash-Wert der zu überprüfenden Objekte.</param>
/// <returns>
/// <c>true</c> falls der AuthHeader gültig und einwandfrei ist, anderenfalls <c>false</c>.
/// </returns>
/// <remarks>n/a</remarks>
public static bool IsVerified(DateTime created, double expires,
string userName, bool isEditMode, byte[] hashValue)
{
bool isVerified = false;
if (isEditMode)
{
if (isNotExpired(created, expires) &&
isHashValid(new object[] { created, expires, userName, isEditMode }, hashValue) &&
isUserVerified(userName))
{
isVerified = true;
}
}
else
{
if (isNotExpired(created, expires) &&
isHashValid(new object[] { created, expires, userName, isEditMode }, hashValue))
{
isVerified = true;
}
}
return isVerified;
}
#endregion
#region private Methods
/// <summary>
/// Private Methode zum überprüfen ob der Zeitintervall noch gültig ist.
/// </summary>
/// <param name="created">Gibt an, wann das Objekt erzeugt wurde.</param>
/// <param name="expires">Gibt den Zeitraum der Gültigkeit des Objekts an.</param>
/// <returns><c>true</c> falls der Zeitraum gültig ist, anderenfalls <c>false</c>.</returns>
private static bool isNotExpired(DateTime created, double expires)
{
if (DateTime.Compare(created.AddSeconds(expires), DateTime.Now) > 0)
{
return true;
}
return false;
}
/// <summary>
/// Private Methode zum überprüfen eines Hash-Wert.
/// </summary>
/// <param name="objArray">Ein Array von Objekten das überprüft werden soll.</param>
/// <param name="hashValue">Der Hash-Wert der zu überprüfenden Objekte.</param>
/// <returns><c>true</c> falls die Überprüfung erfolgreich war, anderenfalls <c>false</c>.</returns>
private static bool isHashValid(object[] objArray, byte[] hashValue)
{
if (Fingerprint.CompareHash(objArray, hashValue))
{
return true;
}
return false;
}
/// <summary>
/// Private Methode zum überprüfen ob ein Benutzer die Rechte zur Datenänderung besitzt.
/// </summary>
/// <param name="userName">Der Name des Benutzers, der im AuthHeader übermittelt wurde.</param>
/// <returns><c>true</c> falls die Benutzer Daten ändern darf, anderenfalls <c>false</c>.</returns>
private static bool isUserVerified(string userName)
{
string role = WebUserManager.GetRole(userName);
if (string.Equals(userName, "anonymus") || !string.Equals(role, "Administrator"))
{
return false;
}
return true;
}
#endregion
#endregion
}Die Methode CompareHash der Klasse Fingerprint erzeugt einen Hash-Wert aus dem übergebenen Objekt-Array und vergleicht diesen mit dem ebenfalls übergebenen Hash-Wert. Ich werde vielleicht in einem späteren Post auf diese Klasse und den Umgang mit Hash-Werten eingehen. Die Methode GetRole aus der Klasse WebUserManager gibt lediglich die höchste zugeordnete Rolle des übergebenen Benutzernamen zurück. Anschließend wird geprüft ob die zurückgegebene Rolle die eines Administrators ist. Damit gewährleiste ich, dass nur Mitglieder der Gruppe Administratoren, auf dem Datenbankserver, Änderungen an den Datenbanken vornehmen können.
Soweit arbeitet das vorgestellte Konzept mit einem benutzerdefiniertem SOAP-Header zur Authentifizierung einwandfrei, solange nicht der erstellte WS-Proxy als Datenquelle eines ObjectDataSource verwendet wird. Dies führt, in der Standard-Benutzung des ObjectDataSource, zu einer Ausnahme des Webdienst mit der Meldung: Authentifizierungs-Header ist korrupt. Das Problem ist zu lösen, doch das ist ein anderes Thema für einen späteren Post.
Technorati-Tags:
Webservice |
DataAccessWenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitte "kicken" sie ihn.
