Bagikan melalui


Menggunakan SSO Secara Efisien dalam Solusi Berorientasi Layanan

Solusi berorientasi layanan menggunakan Enterprise Single Sign-On (SSO) baik untuk menyimpan nilai konfigurasi maupun untuk menangani kredensial untuk sistem back-end. Untuk mengurangi latensi, solusi menggunakan cache lokal untuk nilai konfigurasi. Solusi ini memperbarui cache setiap lima menit.

Dalam banyak aplikasi, adaptor menangani operasi SSO—termasuk mendapatkan tiket SSO, menukarkan tiket, dan menggunakan kredensial untuk mendapatkan akses ke aplikasi afiliasi. Namun, versi sebaris solusi berorientasi layanan tidak menggunakan adaptor. Ini harus menggunakan SSO dari kode.

Topik ini menjelaskan mekanisme penyimpanan sementara yang digunakan oleh solusi, serta bagaimana versi terintegrasi solusi menggunakan SSO melalui kode.

Cache Lokal Nilai Konfigurasi

Solusi berorientasi layanan menggunakan dua objek, ConfigPropertyBag dan ConfigParameters, untuk menangani nilai konfigurasi. Kelas ConfigPropertyBag menyimpan nilai dan hanya digunakan oleh kelas ConfigParameters . Kelas ConfigParameters digunakan oleh bagian lain dari solusi untuk mengambil parameter konfigurasi. Kedua kelas berada di namespace Microsoft.Samples.BizTalk.WoodgroveBank.ConfigHelper .

Nota

Solusi Service Oriented memperbaiki interval refresh cache pada 300 detik (5 menit). Sebagai gantinya, Anda dapat membuat interval refresh cache itu sendiri sebagai properti yang dapat dikonfigurasi dalam solusi ini. Ini dilakukan dalam solusi Manajemen Proses Bisnis. Untuk informasi selengkapnya tentang cara solusi tersebut menangani SSO, lihat Menggunakan SSO Secara Efisien di Solusi Manajemen Proses Bisnis. Perhatikan bahwa, dalam kasus seperti itu, perubahan interval refresh tidak berlaku sampai cache disegarkan pada akhir waktu interval lama.

ConfigPropertyBag memiliki metode berikut:

Metode Deskripsi
Bacalah Mengambil nilai untuk properti tertentu.
Menulis Menetapkan nilai ke properti.

Kelas menggunakan instans .NET NameValueCollection untuk menyimpan nilai. Dua metode akses mengimplementasikan antarmuka IPropertyBag dari namespace Microsoft.BizTalk.SSOClient.Interop . Kelas ConfigPropertyBag adalah kelas internal dan hanya digunakan oleh kelas ConfigParameters .

Nota

Nama kunci dalam tas properti tidak peka huruf besar/kecil. NameValueCollection yang mendasarinya menggunakan hash yang tidak membedakan huruf besar dan kecil serta perbandingan yang tidak membedakan huruf besar dan kecil.

Aplikasi ini menggunakan kelas ConfigParameters untuk menangani nilai konfigurasi SSO. Kelas ini memiliki metode dan atribut publik berikut:

Metode atau Atribut Deskripsi
SSOConfigParameter Enumerasi untuk menentukan parameter konfigurasi.
DapatkanParameterKonfigurasi Metode yang digunakan untuk mengambil nilai untuk parameter tertentu. Menggunakan SSOConfigParameter untuk menunjukkan parameter .

Kelas ConfigParameters menggunakan kelas .NET Timer dan fungsi delegasi untuk menyiapkan refresh 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);  
}  

Perhatikan bahwa konstruktor statis menginisialisasi variabel anggota statis sehingga memungkinkan penggunaan metode kelas tanpa membuat instans kelas. Konstruktor membuat instans penyimpanan konfigurasi SSO (ISSOConfigStore), tas properti konfigurasi (ConfigPropertyBag), dan kunci sinkronisasi (ReaderWriterLock) yang digunakan untuk mengontrol akses ke ConfigurationPropertyBag selama pembaruan dan pembacaan. Konstruktor kemudian menggunakan GetConfigInfo untuk mengambil nilai konfigurasi SSO dan memasukkannya ke dalam tas properti. Terakhir, konstruktor membuat objek Timer yang, setelah interval yang ditentukan, memanggil fungsi delegasi, cacheRefreshCallback.

Fungsi delegasi Timer relatif mudah:

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);  
}  

Perhatikan bahwa metode panggilan balik refresh cache menonaktifkan timer sehingga metode dapat berjalan sepanjang jalan. Perhatikan juga penggunaan kunci untuk mengontrol akses ke tas properti. ReaderWriterLock adalah pilihan terbaik di sini—ini dirancang untuk kasus di mana ada lebih banyak bacaan daripada penulisan. Perhatikan juga bahwa kunci, syncLock, bersifat statis dan dinyatakan pada tingkat kelas sehingga semua utas berbagi satu instans.

Menggunakan SSO dari Kode

Saat menggunakan single sign-on dari kode, kode harus berperan sebagai adaptor: yaitu, mengambil tiket SSO dari pesan, menukarkan tiket untuk mendapatkan nama pengguna dan kata sandi untuk sistem back-end, dan akhirnya menggunakan sistem back-end. Solusi berorientasi layanan melakukan ini melalui metode GetPendingTransactionsResponse dari objek PendingTransactionsCaller .

Metode ini muncul sebagai berikut:

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;  
    }  
}  

Metode ini dimulai dengan mengambil informasi konfigurasi, termasuk URL, untuk sistem back-end dan nama aplikasi backend (afiliasi).

Untuk menukarkan tiket, metode harus mengekstrak tiket dan nama pengguna asli yang meminta dari pesan. Pesan berisi tiket sebagai salah satu properti konteks pesan, BTS.SSOTicket. Untuk informasi selengkapnya, lihat Properti Konteks Pesan dalam panduan UI dan referensi namespace API pengembang. Metode ini juga mengekstrak OriginatorSID dari properti konteks pesan. Dengan tiket dan nama pengirim di tangan, metode RedeemTicket pada tiket dipanggil untuk mengambil kredensial.

Sisa kode membuat cache .NET NetworkCredential untuk kredensial dan memanggil layanan Web back-end.

Nota

Karena nama pengguna dan kata sandi kembali dari SSO dalam teks yang jelas, Anda ingin meminimalkan masa pakai variabel yang menyimpan informasi tersebut. Perhatikan bahwa kode mendeklarasikan variabel kredensial dalam blok coba . Di sini, variabel kedaluwarsa saat keluar dari blok coba .

Lihat Juga

Sorotan Implementasi Solusi Berorientasi Layanan