Freigeben über


Implementieren von IMFNetCredentialManager

Führen Sie in der IMFNetCredentialManager::BeginGetCredentials-Methode die folgenden Schritte aus.

  1. Wenn Sie noch keinen IMFNetCredentialCache-Zeiger haben, rufen Sie MFCreateCredentialCache auf, um das Anmeldeinformationscacheobjekt zu erstellen. Speichern Sie diesen Zeiger.
  2. Rufen Sie IMFNetCredentialCache::GetCredential auf. Legen Sie die Flags im dwAuthenticationFlags-Parameter wie folgt fest:
    • Wenn der hrOp-Member der MFNetCredentialManagerGetParam-Strukturgleich NS_E_PROXY_ACCESSDENIED ist, legen Sie das flag MFNET_AUTHENTICATION_PROXY fest.
    • Wenn fClearTextPackageauf TRUE festgelegt ist, legen Sie das flag MFNET_AUTHENTICATION_CLEAR_TEXT fest.
    • Wenn fAllowLoggedOnUserauf TRUE festgelegt ist, legen Sie das flag MFNET_AUTHENTICATION_LOGGED_ON_USER fest.
  3. Die GetCredential-Methode gibt einen IMFNetCredential-Zeiger und möglicherweise das flag REQUIRE_PROMPT zurück. Speichern Sie den IMFNetCredential-Zeiger .
  4. Wenn GetCredential das REQUIRE_PROMPT-Flag nicht zurückgibt, sind Sie fertig. Fahren Sie mit Schritt 9 fort.
  5. Wenn GetCredential das REQUIRE_PROMPT-Flag zurückgibt, müssen Sie den Benutzer zur Eingabe seines Benutzernamens und Kennworts auffordern.
  6. Wenn fClearTextPackageauf FALSE festgelegt ist, verschlüsseln Sie die Anmeldeinformationen.
  7. Rufen Sie IMFNetCredential::SetUser und IMFNetCredential::SetPassword auf, um den Namen und das Kennwort des Benutzers für das Anmeldeinformationsobjekt festzulegen.
  8. Rufen Sie optional IMFNetCredentialCache::SetUserOptions auf, um das Anmeldeinformationscacheobjekt mit den Einstellungen des Benutzers zum Speichern und Senden von Anmeldeinformationen zu aktualisieren.
  9. Rufen Sie den IMFAsyncCallback-Rückruf auf, indem Sie MFInvokeCallback aufrufen.

Geben Sie in der IMFNetCredentialManager::EndGetCredentials-Methode den ZEIGEr IMFNetCredential zurück, der in der BeginGetCredentials-Methode abgerufen wurde.

Übergeben Sie in der IMFNetCredentialManager::SetGood-Methode die Eingabeparameter direkt an die IMFNetCredentialCache::SetGood-Methode . Dadurch wird der Anmeldeinformationscache benachrichtigt, ob die Anmeldeinformationen vom Server akzeptiert wurden.

Wenn Sie den Benutzer auffordern (Schritt 5) oder die Anmeldeinformationen verschlüsseln müssen (Schritt 6), sollten Sie dies in einem Arbeitswarteschlangenthread tun, damit Sie die Microsoft Media Foundation-Pipeline nicht blockieren. Rufen Sie MFPutWorkItem auf, und führen Sie dann die verbleibenden Schritte innerhalb des Arbeitswarteschlangenrückrufs aus.

Hinweis

Beachten Sie, dass BeginGetCredentials möglicherweise aufgerufen wird, während die Netzwerkquelle erstellt wird. Wenn Sie also die Netzwerkquelle durch Aufrufen der synchronen IMFSourceResolver::CreateObjectFromURL-Methode erstellen, kann Ihr aufrufender Thread während des Abrufens der Anmeldeinformationen blockiert werden. Daher wird empfohlen, stattdessen die asynchrone IMFSourceResolver::BeginCreateObjectFromURL-Methode zu verwenden.

 

Beispiel

Dieses Beispiel zeigt eine Art von Verhalten, das ein Anmeldeinformations-Manager bereitstellen kann.

Hier ist eine Deklaration der -Klasse, die IMFNetCredentialManager implementiert.

class CCredentialManager : public IMFNetCredentialManager, IMFAsyncCallback 
{
    long                    m_cRef;
    IMFNetCredentialCache   *m_pCredentialCache;

public:
    CCredentialManager () : m_cRef(1), m_pCredentialCache(NULL)
    { 
    }
    ~CCredentialManager()
    {
        SafeRelease(&m_pCredentialCache);
    }

    STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CCredentialManager, IMFNetCredentialManager),
            QITABENT(CCredentialManager, IMFAsyncCallback),
            { 0 }
        };
        return QISearch(this, qit, riid, ppv);
    }      

    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        LONG cRef = InterlockedDecrement(&m_cRef);
        if (cRef == 0)
        {
            delete this;
        }
        return cRef;
    }

    STDMETHODIMP BeginGetCredentials(
        MFNetCredentialManagerGetParam* pParam,
        IMFAsyncCallback* pCallback,
        IUnknown* pState
        );

    STDMETHODIMP EndGetCredentials(
        IMFAsyncResult* pResult, 
        IMFNetCredential** ppCred);

    STDMETHODIMP SetGood(IMFNetCredential* pCred, BOOL fGood)
    {
        if (!pCred)
        {
            return E_POINTER;
        }

        return m_pCredentialCache->SetGood(pCred, fGood);
    }


    STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
    {
        return E_NOTIMPL;
    }

    STDMETHODIMP Invoke(IMFAsyncResult* pResult);
};

Um den Status des BeginGetCredentials-Vorgangs nachzuverfolgen, verwendet die -Klasse das folgende Hilfsobjekt:

// Holds state information for the GetCredentials operation, so that work can 
// be moved to a work-queue thread.

struct CredentialOp : public IUnknown
{
    long                m_cRef;
    IMFNetCredential    *m_pCredential;
    DWORD               m_dwFlags;

    CredentialOp(IMFNetCredential *pCredential) 
        : m_cRef(1), m_dwFlags(0), m_pCredential(pCredential)
    {
        m_pCredential->AddRef();
    }

    ~CredentialOp()
    {
        SafeRelease(&m_pCredential);
    }

    STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CredentialOp, IUnknown),
            { 0 }
        };
        return QISearch(this, qit, riid, ppv);
    }      

    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        LONG cRef = InterlockedDecrement(&m_cRef);
        if (cRef == 0)
        {
            delete this;
        }
        return cRef;
    }
};

Die BeginGetCredentials-Methode erstellt den Anmeldeinformationscache und ruft einen IMFNetCredential-Zeiger ab. Wenn der Benutzer aufgefordert werden muss (durch das flag REQUIRE_PROMPT angegeben), ruft die Methode MFPutWorkItem auf, um ein neues Arbeitselement in die Warteschlange zu stellen:

STDMETHODIMP CCredentialManager::BeginGetCredentials(
    MFNetCredentialManagerGetParam* pParam,
    IMFAsyncCallback* pCallback,
    IUnknown* pState
    )
{
    if (!pParam || !pCallback)
    {
        return E_POINTER;
    }

    DWORD dwAuthenticationFlags = 0;
    DWORD dwRequirementFlags = 0;

    if (pParam->hrOp == NS_E_PROXY_ACCESSDENIED)
    {
        dwAuthenticationFlags |= MFNET_AUTHENTICATION_PROXY;
    }

    if (pParam->fAllowLoggedOnUser)
    {
        dwAuthenticationFlags |= MFNET_AUTHENTICATION_LOGGED_ON_USER;
    }

    if (pParam->fClearTextPackage)
    {
        dwAuthenticationFlags |= MFNET_AUTHENTICATION_CLEAR_TEXT;
    }

    IMFNetCredential *pCredential =  NULL;
    IMFAsyncResult* pResult = NULL;

    HRESULT hr = S_OK;

    if (m_pCredentialCache == NULL)
    {
        hr = MFCreateCredentialCache(&m_pCredentialCache);
        if (FAILED(hr))
        {
            goto done;
        }
    }

    hr = m_pCredentialCache->GetCredential(
        pParam->pszUrl, 
        pParam->pszRealm, 
        dwAuthenticationFlags, 
        &pCredential, 
        &dwRequirementFlags
        );

    if (FAILED(hr))
    {
        goto done;
    }

    if( ( dwRequirementFlags & REQUIRE_PROMPT ) == 0 )
    {
        // The credential is good to use. Prompting the user is not required.
        hr = S_OK;
        goto done;
    }

    // The credential requires prompting the user. 
    CredentialOp *pOp = new (std::nothrow) CredentialOp(pCredential);

    if (pOp == NULL)
    {
        hr = E_OUTOFMEMORY;
        goto done;
    }

    // Set flags. Use these to inform the user if the credentials will
    // be sent in plaintext or saved in the credential cache.

    if (pParam->fClearTextPackage)
    {
        // Notify the user that credentials will be sent in plaintext.
        pOp->m_dwFlags |= MFNET_CREDENTIAL_ALLOW_CLEAR_TEXT;
    }

    if(dwRequirementFlags & REQUIRE_SAVE_SELECTED )
    {
        // Credentials will be saved in the cache by default.
        pOp->m_dwFlags |= MFNET_CREDENTIAL_SAVE;
    }

    // NOTE: The application should enable to user to deselect these two flags;
    // for example, through check boxes in the prompt dialog.


    // Now queue the work item.

    hr = MFCreateAsyncResult(pOp, pCallback, pState, &pResult);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION, this, pResult);

done:
    SafeRelease(&pResult);
    SafeRelease(&pCredential);
    SafeRelease(&pOp);
    return hr;
}

Der Arbeitswarteschlangenthread ruft Invoke auf, der den Benutzer auffordert und dann MFInvokeCallback aufruft, um den Rückrufzeiger aufzurufen, der in BeginGetCredentials bereitgestellt wurde.

STDMETHODIMP CCredentialManager::Invoke(IMFAsyncResult* pResult)
{
    IUnknown *pState = NULL;
    IMFAsyncResult *pGetCredentialsResult = NULL;
    IUnknown *pOpState = NULL;

    CredentialOp *pOp = NULL;   // not AddRef'd

    HRESULT hr = pResult->GetState(&pState);

    if (SUCCEEDED(hr))
    {
        hr = pState->QueryInterface(IID_PPV_ARGS(&pGetCredentialsResult));
    }

    if (SUCCEEDED(hr))
    {
        hr = pGetCredentialsResult->GetObject(&pOpState);
    }

    if (SUCCEEDED(hr))
    {
        pOp = static_cast<CredentialOp*>(pOpState);

        // Display a dialog for the user to enter user name and password.
        hr = PromptUserCredentials(pOp);
    }

    if (SUCCEEDED(hr) && m_pCredentialCache)
    {
        // Update with options set by the user.
        hr = m_pCredentialCache->SetUserOptions(
            pOp->m_pCredential, 
            pOp->m_dwFlags
            );
    }

    if (pGetCredentialsResult)
    {
        pGetCredentialsResult->SetStatus(hr);
        MFInvokeCallback(pGetCredentialsResult);
    }

    SafeRelease(&pState);
    SafeRelease(&pGetCredentialsResult);
    SafeRelease(&pOpState);
    return S_OK;
}

Die EndGetCredentials-Methode schließt den Vorgang ab, indem der IMFNetCredential-Zeiger an den Aufrufer zurückgegeben wird.

STDMETHODIMP CCredentialManager::EndGetCredentials(
    IMFAsyncResult* pResult, 
    IMFNetCredential** ppCred
    )
{
    if (!pResult || !ppCred)
    {
        return E_POINTER;
    }

    *ppCred = NULL;

    IUnknown *pUnk = NULL;

    // Check the result of the asynchronous operation.
    HRESULT hr = pResult->GetStatus();

    if (FAILED(hr))
    {
        // The operation failed.
        goto done;
    }

    hr = pResult->GetObject(&pUnk);
    if (FAILED(hr))
    {
        goto done;
    }

    CredentialOp *pOp = static_cast<CredentialOp*>(pUnk);

    *ppCred = pOp->m_pCredential;
    pOp->m_pCredential = NULL;

done:
    SafeRelease(&pUnk);
    return hr;
}

Netzwerkquellenauthentifizierung