Standardmäßig ist es bei Citrix XenApp 6.0 nicht möglich, Anmeldedaten von Benutzern vorzublenden. Eine mögliche Lösung ist hierbei die Abfrage von Client-Namen via DNS Reverse Lookup Zone und Ermittlung von Username via ActiveX-Unterstützung unter Windows. Bei der Lösung wird ein Windows Server 2008R2 mit IIS und aspx-Dateien verwendet. Über die aspx-Dateien werden diverse js-Dateien eingebunden. Hier empfiehlt sich ggf. die Verwendung von festen IPs von Thin Clients auf Linux-Basis. Bei Clients unter Windows muss Active X-Unterstützung für den Web Browser und dem jeweils verwendeten Server/URL-Pfad aktiviert sein. Zusätzlich besteht die Möglichkeit zur Verwendung von URL-Parametern, wobei dies nicht besonders elegant ist.

Ganz wichtig: Unbedingt die Originale login.js sichern. Jeder Fehler sorgt dafür, dass die gesamte Anmeldung nicht mehr möglich ist.

Ich übernehme keine Verantwortung für eventuelle Probleme.

Im Verzeichnis inetpub\wwwroot\Citrix\XenApp\auth\clientscripts des Servers, für die Verwaltung der Sitzungen, befindet sich die Datei login.js mit folgender Funktion onLoadLayout (Zeile 81 bis 104).

function onLoadLayout() {
    <% // Properly display the login button if high contrast mode is enabled. %>
    maintainAccessibility("LoginButton");

    var frame = getTopFrame(window);
    if (frame != null) {
        frame.location.href = "<%=Constants.PAGE_LOGGEDOUT%>";
        return false;
    }

    var form = document.forms[0];
    if (form) {
        setFocus(form);
<% // ensure that the domain is greyed out if appropriate %>
        onUsernameTextEntry(form);
    }

    var accountSSlink = document.getElementById("<%=Constants.ID_ACCOUNTSS%>");

    if (accountSSlink != null) {
        showAccountSelfServiceIfEnabled(accountSSlink);
    }
    return;
}

Diese Datei können wir über entsprechend notwendige Funktionen erweitern (einfach oberhalb der Funktion onLoadLayout):

function onLoadLayout_loginextension () {

    clientIP = '<%= Request.ServerVariables["REMOTE_ADDR"]%>';

    try {
    
        //Pruefe auf Variablen Computername, Clientname, Username via ActiveX - Voraussetzung: Windows-Client mit Browser-Unterstützung fuer Active X-Elemente
        
        WshShell = new ActiveXObject("WScript.Shell");
        ComputerName = WshShell.ExpandEnvironmentStrings("%computername%");
        ClientName = WshShell.ExpandEnvironmentStrings("%clientname%");
        UserName = WshShell.ExpandEnvironmentStrings("%username%");

        // Pruefe auf Computer beginnend auf Name "pc-" und verwende diesen, sonst verwende Username
        if (ComputerName.toLowerCase().substring(0,3) == "pc-") {
            document.forms[0].<%=Constants.ID_USER%>.value = ComputerName;
            } else { document.forms[0].<%=Constants.ID_USER%>.value = UserName; }

        } catch (e) {

            //Wenn nicht erfolgreich über Active X, dann frage DNS des Servers ab
        
            clientUserName = '';

            try {

            //Abfrage Variable HostName bzw IP-Adresse
            clientDNS = '<%=""+System.Net.Dns.GetHostEntry(Convert.ToString(Request.ServerVariables["remote_addr"])).HostName%>';
            clientDNSParts = clientDNS.split (".");
            clientUserName = clientDNSParts[0];
            
            //Beispiel: Pruefe auf IP4-Netzwerk beginnend mit 192, dann verwende '',
            //Sonst pruefe auf DNS-Clientname test, dann verwende '',
            //Sonst pruefe auf DNS-Clientname beginnend "pc-", dann verwende ''
            
            if (clientUserName == "192") {clientUserName = ''}
                else if (clientUserName.toLowerCase() == "test") {clientUserName = ''}
                    else if (clientUserName.toLowerCase().substring(0,3) == "pc-") {clientUserName = ''}
            } catch (e) {}

            document.forms[0].<%=Constants.ID_USER%>.value = clientUserName;
    
        }

    }

Innerhalb der Funktion onLoadLayout_loginextension wird über

document.forms[0].<%=Constants.ID_USER%>.value = ...

die Zuweisung innerhalb der aspx-Datei durchgeführt. Zusätzlich wird in der Funktion onLoadLayout zu Beginn:

onLoadLayout_loginextension ();

eingefügt.

XenApp_loginjs_01

Die zusätzliche Zeile

clientIP += '<%= Request.ServerVariables["REMOTE_ADDR"]%>';

dient für weitere mögliche Auswertungen auf Basis der IP-Adresse, zum Beispiel, damit bei lokalem Zugriff auf den Server, die Funktion nicht verwendet wird. Diese kann in der Funktion onLoadLayout entfallen. Beispiel bei Verwendung:

if (clientIP == '192.1.2.3') {clientUserName = 'administrator';}

Anmerkung:

clientIP += '<%= Request.ServerVariables["REMOTE_HOST"]%>';

funktioniert nicht.

Wenn jetzt jedoch, zum Beispiel weil der Client kein Active X unterstützt und die IP dynamisch vergeben wird oder andere Probleme vorliegen, besteht die Möglichkeit den Usernamen als Variable zum Auruf zu übergeben. Voraussetzung ist die Verwendung des Aufrufs über:

http://servername/Citrix/XenApp/auth/login.aspx?username=test12345

und dass die login.js statt der oben aufgeführten Funktion onLoadLayout_loginextension um die folgenden erweitert wird. Der Aufruf muss auch hier, wie beschrieben, über die Funktion onLoadLayout erfolgen.

function getUrlVars_loginextension()
{
    //Lese alle URL-Parameter in ein Array
    
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    
    return vars;

}

function createCookie_loginextension(name,value,seconds) {

    //Erzeuge ein Cookie mit ausreichender Lebenszeit

    if (seconds) {
        var date = new Date();
        date.setTime(date.getTime()+(seconds*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie_loginextension(name) {

    //Lese das Cookie aus

    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

function onLoadLayout_loginextension () {

    clientIP = '<%= Request.ServerVariables["REMOTE_ADDR"]%>';
    
    var UrlVar_UserName = ''
        
    //Lese Cookie aus
    COOKIE_USERNAME = 'loginextension_username'
    var CookieUserName = readCookie_loginextension(COOKIE_USERNAME)
    if (CookieUserName) {
        UrlVar_UserName = CookieUserName;
    }
    
    //Wenn URL-Parameter username uebergeben wurde, dann lese diesen und schreibe ihn in das Cookie
    var UrlVars = getUrlVars_loginextension()
    if ('username' in UrlVars) {
        UrlVar_UserName = UrlVars["username"].toString();
        createCookie_loginextension(COOKIE_USERNAME,UrlVar_UserName,300);
        }

    try {
    
        //Pruefe auf Variablen Computername, Clientname, Username via ActiveX - Voraussetzung: Windows-Client mit Browser-Unterstützung fuer Active X-Elemente
        
        WshShell = new ActiveXObject("WScript.Shell");
        ComputerName = WshShell.ExpandEnvironmentStrings("%computername%");
        ClientName = WshShell.ExpandEnvironmentStrings("%clientname%");
        UserName = WshShell.ExpandEnvironmentStrings("%username%");

        // Pruefe auf Computer beginnend auf Name "pc-" und verwende diesen, sonst verwende Username
        if (ComputerName.toLowerCase().substring(0,3) == "pc-") {
            document.forms[0].<%=Constants.ID_USER%>.value = ComputerName;
            } else { document.forms[0].<%=Constants.ID_USER%>.value = UserName; }

        } catch (e) {

            //Wenn nicht erfolgreich über Active X, dann frage DNS des Servers ab
        
            clientUserName = '';

            try {

            //Abfrage Variable HostName bzw IP-Adresse
            clientDNS = '<%=""+System.Net.Dns.GetHostEntry(Convert.ToString(Request.ServerVariables["remote_addr"])).HostName%>';
            clientDNSParts = clientDNS.split (".");
            clientUserName = clientDNSParts[0];
            
            //Beispiel: Pruefe auf IP4-Netzwerk beginnend mit 192, dann verwende '',
            //Sonst pruefe auf DNS-Clientname test, dann verwende '',
            //Sonst pruefe auf DNS-Clientname beginnend "pc-", dann verwende ''
            
            if (clientUserName == "192") {clientUserName = ''}
                else if (clientUserName.toLowerCase() == "test") {clientUserName = ''}
                    else if (clientUserName.toLowerCase().substring(0,3) == "pc-") {clientUserName = ''}
            } catch (e) {}

            document.forms[0].<%=Constants.ID_USER%>.value = clientUserName;
    
        }
    
    //Wenn UrlVar_UserName durch Parameteruebergabe oder Auslesen des Cookie vorliegt, dann verwende diesen (alle Werte davor werden ueberschrieben)
    if (UrlVar_UserName != '') {
        document.forms[0].<%=Constants.ID_USER%>.value = UrlVar_UserName;
        }

    }

Die Variante über Cookies ist nicht besonders elegant, jedoch hatte ich keine Lösung gefunden, wie die Parameter sonst übergeben werden können, da immer mehrere Skripte für ClientDetection etc. ausgeführt werden und die entsprechenden Parameter immer erneut übergeben werden müssen.

Im Ergebnis sieht es dann in etwa so aus:

XenApp_loginjs_02