Partager via


Utilisation efficace de l’authentification unique dans la solution orientée service

La solution orientée services utilise l'authentification unique de l'entreprise (SSO) pour stocker les valeurs de configuration et pour gérer les informations d'identification pour les systèmes principaux. Pour réduire la latence, la solution utilise un cache local pour les valeurs de configuration. La solution actualise le cache toutes les cinq minutes.

Dans de nombreuses applications, les adaptateurs gèrent les applications SSO, notamment en obtenant un ticket SSO, en échangeant le ticket et en utilisant les informations d'identification pour accéder à l'application associée. Toutefois, la version Inline de la solution orientée services n'utilise pas d'adaptateurs. Elle doit utiliser l'authentification unique à partir du code.

Cette rubrique décrit le mécanisme de mise en cache utilisé par la solution ainsi que l'utilisation de l'authentification unique à partir du code par la version Inline de la solution.

Mise en cache local des valeurs de configuration

La solution orientée service utilise deux objets, ConfigPropertyBag et ConfigParameters, pour gérer les valeurs de configuration. La classe ConfigPropertyBag contient les valeurs et est utilisée uniquement par la classe ConfigParameters . La classe ConfigParameters est utilisée par les autres parties de la solution pour récupérer les paramètres de configuration. Les deux classes se trouvent dans l’espace de noms Microsoft.Samples.BizTalk.WoodgroveBank.ConfigHelper .

Notes

La solution orientée services définit l'intervalle d'actualisation du cache sur 300 secondes (5  minutes). Vous pouvez, à la place, faire de l’intervalle d’actualisation du cache lui-même une propriété configurable dans cette solution. Cela est effectué dans la solution de gestion des processus d'entreprise. Pour plus d’informations sur la façon dont cette solution gère l’authentification unique, consultez Utilisation efficace de l’authentification unique dans la solution de gestion des processus métier. Notez que, dans un tel cas, une modification de l'intervalle d'actualisation ne prend effet qu'au moment où le cache est actualisé à la fin de l'ancien intervalle.

ConfigPropertyBag utilise les méthodes suivantes :

Méthode Description
Lire Extrait une valeur pour une propriété donnée.
Write Attribue une valeur à une propriété.

La classe utilise une instance d’un .NET NameValueCollection pour contenir les valeurs. Les deux méthodes d’accès implémentent l’interface IPropertyBag à partir de l’espace de noms Microsoft.BizTalk.SSOClient.Interop . La classe ConfigPropertyBag est une classe interne utilisée uniquement par la classe ConfigParameters .

Notes

Les noms de clé dans le jeu de propriétés ne respectent pas la casse. Le NameValueCollection sous-jacent utilise un hachage non respectant la casse et des comparaisons qui ne respectent pas la casse.

L’application utilise la classe ConfigParameters pour gérer les valeurs de configuration de l’authentification unique. La classe possède les méthodes publiques et attributs suivants :

Méthode ou attribut Description
SSOConfigParameter Énumération pour spécifier les paramètres de configuration.
GetConfigParameters Méthode utilisée pour récupérer une valeur pour un paramètre donné. Utilise SSOConfigParameter pour indiquer le paramètre.

La classe ConfigParameters utilise la classe .NET Timer et une fonction déléguée pour configurer l’actualisation de ConfigPropertyBag :

private static Timer cacheRefreshTimer;  
private static ISSOConfigStore ssoConfigStore;  
private static ReaderWriterLock syncLock;  
  
// Cache refresh interval in milliseconds  
private const int CacheRefreshInterval = 5 * 60 * 1000;  
private static ConfigPropertyBag ssoPropBag;  
  
static ConfigParameters()  
{  
    ssoConfigStore = new ISSOConfigStore();  
    ssoPropBag = new ConfigPropertyBag();  
    syncLock = new ReaderWriterLock();  
  
    ssoConfigStore.GetConfigInfo(SSO_CONFIG_APP,  
         SSO_IDENTIFIER_NAME, SSOFlag.SSO_FLAG_RUNTIME,  
         ssoPropBag);  
  
    cacheRefreshTimer = new Timer(  
        new TimerCallback(ConfigParameters.cacheRefreshCallback),  
        null, CacheRefreshInterval, CacheRefreshInterval);  
}  

Notez que le constructeur statique initialise les variables de membres statiques, permettant ainsi l'utilisation de méthodes de classe sans créer d'instance de la classe. Le constructeur crée des instances du magasin de configuration de l’authentification unique (ISSOConfigStore), du sac de propriétés de configuration (ConfigPropertyBag) et d’un verrou de synchronisation (ReaderWriterLock) utilisé pour contrôler l’accès à ConfigurationPropertyBag pendant les mises à jour et les lectures. Le constructeur utilise ensuite GetConfigInfo pour récupérer les valeurs de configuration de l’authentification unique et les placer dans le conteneur de propriétés. Enfin, le constructeur crée un objet Timer qui, après l’intervalle spécifié, appelle la fonction déléguée cacheRefreshCallback.

La fonction de délégué du minuteur est relativement simple :

private static void cacheRefreshCallback(object state)  
{  
    // Disable the timer until we are done loading the cache.  
    cacheRefreshTimer.Change(Timeout.Infinite, CacheRefreshInterval);  
  
    // Put the data from SSO in a new property bag so that  
    // we don't have to lock the property bag and block it from being  
    // used. The SSO call is a remote call and may take a while.  
    ConfigPropertyBag propBag2 = new ConfigPropertyBag();  
    ssoConfigStore.GetConfigInfo(SSO_CONFIG_APP,   
        SSO_IDENTIFIER_NAME, SSOFlag.SSO_FLAG_RUNTIME, propBag2);  
  
    // Get a writer lock before updating the cached values.  
    syncLock.AcquireWriterLock(Timeout.Infinite);  
  
    try  
    {  
        ssoPropBag = propBag2;  
    }  
    finally   
    {  
        syncLock.ReleaseWriterLock();  
    }  
    // Enable the timer.  
    cacheRefreshTimer.Change(CacheRefreshInterval,   
        CacheRefreshInterval);  
}  

Notez que la méthode de rappel d'actualisation du cache désactive le minuteur afin que la méthode puisse s'exécuter complètement. Remarquez également l'utilisation des verrous pour contrôler l'accès au jeu de propriétés. Le ReaderWriterLock est le meilleur choix ici : il est conçu pour les cas où il y a plus de lectures que d’écritures. Notez également que le verrou, syncLock, est statique et déclaré au niveau de la classe que tous les threads partagent le même instance unique.

Utilisation de l'authentification unique à partir du code

Lors de l’utilisation de l’authentification unique à partir du code, le code doit prendre le rôle de l’adaptateur : c’est-à-dire récupérer le ticket d’authentification unique à partir du message, échanger le ticket pour obtenir le nom d’utilisateur et le mot de passe pour le système principal et, enfin, utiliser le système principal. La solution orientée service effectue cette opération via la méthode GetPendingTransactionsResponse de l’objet PendingTransactionsCaller .

La méthode apparaît comme suit :

public static PendingTransactionsResponse GetPendingTransactionsResponse(XLANGMessage requestMsg)  
{  
    try  
    {  
        // Get config parameter values.  
        int ptTimeout = Convert.ToInt32(  
            ConfigParameters.GetConfigParameter(  
                ConfigParameters.  
                    SSOConfigParameter.  
                        PENDING_TRANSACTIONS_INLINE_TIMEOUT  
            )  
        );  
  
        string ptURL = ConfigParameters.GetConfigParameter(  
            ConfigParameters.  
                SSOConfigParameter.  
                    PENDING_TRANSACTIONS_URL  
        );  
        string ssoAffliateApp = ConfigParameters.  
            GetConfigParameter(ConfigParameters.  
                SSOConfigParameter.  
                    PENDING_TRANSACTIONS_SSO_AFFILIATE_APP  
            );  
  
        // Redeem the SSO ticket and get the userid/password to   
        // use to interact with Pending Transaction System.  
  
        // Extract the ticket…  
        string msgTicket = (string)requestMsg.  
            GetPropertyValue(typeof(BTS.SSOTicket));  
  
        // and the user name of the originating user.  
        string originatorSID = (string)requestMsg.  
            GetPropertyValue(  
                typeof(  
                    Microsoft.BizTalk.XLANGs.BTXEngine.OriginatorSID  
                )  
            );  
  
        string pendTransUserName;  
        // Now, redeem the ticket.  
        string[] pendTransCredential =   
            ssoTicket.RedeemTicket(  
                ssoAffliateApp,  
                originatorSID,  
                msgTicket,  
                SSOFlag.SSO_FLAG_NONE,  
                out pendTransUserName  
            );   
  
        PendingTransactionsRequest req =   
            (PendingTransactionsRequest)requestMsg[0].  
                RetrieveAs(  
                    typeof(PendingTransactionsRequest)  
                );  
        PendingTransactionsResponse resp;  
  
        using (PendingTransactionsWebService  
            svc = new PendingTransactionsWebService())  
        {  
            svc.Url = ptURL;  
            svc.Timeout = ptTimeout;  
  
            // The web service uses basic authentication, so we  
            //need to send the user id and password in the request.  
            CredentialCache credCache = new CredentialCache();  
            NetworkCredential credentialToUse =  
                new NetworkCredential(  
                    pendTransUserName, pendTransCredential[0]  
                );  
            credCache.Add(new Uri(svc.Url), "Basic", credentialToUse);  
            svc.Credentials = credCache;  
  
            resp = svc.GetPendingTransactions(req);  
        }  
        return resp;                  
    }  
    catch (System.Net.WebException webEx)  
    {  
        if (webEx.Status == WebExceptionStatus.Timeout)  
        {  
            throw new PendingTransactionsTimeoutException();  
        }  
        else  
        {  
            Trace.WriteLine("Other Net.WebException: "  
                + webEx.ToString()   
                + (null == webEx.InnerException ? "" :  
                     ("Inner Exception: "   
                        + webEx.InnerException.ToString())  
                )  
            );  
            throw;  
        }  
    }  
    catch(System.Exception ex)  
    {  
        Trace.WriteLine("Other Exception: "  
            + ex.ToString()   
            + (null == ex.InnerException ? "" :   
                 ("Inner Exception: "  
                    + ex.InnerException.ToString())  
                  )  
            );  
        throw;  
    }  
}  

La méthode commence par récupérer les informations de configuration, notamment l'URL, pour le système principal et le nom de l'application principale (associée).

Pour échanger le ticket, la méthode doit extraire du message le ticket et le nom d'utilisateur à l'origine de la demande. Le message contient le ticket en tant que l’une des propriétés de contexte de message, BTS. SSOTicket. Pour plus d’informations, consultez Propriétés du contexte de message dans l’aide de l’interface utilisateur et informations de référence sur l’espace de noms d’API des développeurs. La méthode extrait également l’OriginatorSID des propriétés de contexte de message. Avec le ticket et le nom de l'expéditeur, la méthode appelle la méthode RedeemTicket sur le ticket pour récupérer les informations d'identification.

Le reste du code crée un cache .NET NetworkCredential pour les informations d'identification et appelle le service Web principal.

Notes

Comme le nom d'utilisateur et le mot de passe reviennent de l'authentification unique en texte clair, vous devez minimiser la durée de vie des variables contenant ces informations. Notez que le code déclare les variables d’informations d’identification dans un bloc try . Ici, les variables expirent à la sortie du bloc try .

Voir aussi

Caractéristiques de l’implémentation de la solution orientée services