Implémentation de IMFNetCredentialManager
Dans la méthode IMFNetCredentialManager::BeginGetCredentials , procédez comme suit.
- Si vous ne disposez pas déjà d’un pointeur IMFNetCredentialCache , appelez MFCreateCredentialCache pour créer l’objet de cache d’informations d’identification. Stockez ce pointeur.
- Appelez IMFNetCredentialCache::GetCredential. Définissez les indicateurs dans le paramètre dwAuthenticationFlags comme suit :
- Si le membre hrOp de la structure MFNetCredentialManagerGetParam est égal à NS_E_PROXY_ACCESSDENIED, définissez l’indicateur MFNET_AUTHENTICATION_PROXY .
- Si fClearTextPackage a la valeur TRUE, définissez l’indicateur MFNET_AUTHENTICATION_CLEAR_TEXT .
- Si fAllowLoggedOnUser a la valeur TRUE, définissez l’indicateur MFNET_AUTHENTICATION_LOGGED_ON_USER .
- La méthode GetCredential retourne un pointeur IMFNetCredential et éventuellement l’indicateur REQUIRE_PROMPT. Stockez le pointeur IMFNetCredential .
- Si GetCredential ne retourne pas l’indicateur REQUIRE_PROMPT , vous avez terminé. Passez à l’étape 9.
- Sinon, si GetCredential retourne l’indicateur REQUIRE_PROMPT , vous devez demander à l’utilisateur de lui fournir son nom d’utilisateur et son mot de passe.
- Si fClearTextPackage a la valeur FALSE, chiffrez les informations d’identification.
- Appelez IMFNetCredential::SetUser et IMFNetCredential::SetPassword pour définir le nom et le mot de passe de l’utilisateur sur l’objet d’informations d’identification.
- Si vous le souhaitez, appelez IMFNetCredentialCache::SetUserOptions pour mettre à jour l’objet de cache d’informations d’identification avec les préférences de l’utilisateur pour le stockage et l’envoi des informations d’identification.
- Appelez le rappel IMFAsyncCallback en appelant MFInvokeCallback.
Dans la méthode IMFNetCredentialManager::EndGetCredentials , retournez le pointeur IMFNetCredential obtenu dans la méthode BeginGetCredentials .
Dans la méthode IMFNetCredentialManager::SetGood , passez les paramètres d’entrée directement à la méthode IMFNetCredentialCache::SetGood . Cela avertit le cache des informations d’identification si les informations d’identification ont été acceptées par le serveur.
Si vous devez inviter l’utilisateur (étape 5) ou chiffrer les informations d’identification (étape 6), vous devez le faire sur un thread de file d’attente de travail, afin de ne pas bloquer le pipeline Microsoft Media Foundation. Appelez MFPutWorkItem , puis effectuez les étapes restantes à l’intérieur du rappel de file d’attente de travail.
Notes
N’oubliez pas que BeginGetCredentials peut être appelé pendant la création de la source réseau. Par conséquent, si vous créez la source réseau en appelant la méthode IMFSourceResolver::CreateObjectFromURL synchrone, votre thread appelant peut se bloquer pendant l’acquisition des informations d’identification. Par conséquent, il est recommandé d’utiliser la méthode asynchrone IMFSourceResolver::BeginCreateObjectFromURL à la place.
Exemple
Cet exemple montre un type de comportement qu’un gestionnaire d’informations d’identification peut fournir.
Voici une déclaration de la classe qui implémente IMFNetCredentialManager.
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);
};
Pour suivre l’état de l’opération BeginGetCredentials , la classe utilise l’objet d’assistance suivant :
// 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;
}
};
La méthode BeginGetCredentials crée le cache d’informations d’identification et obtient un pointeur IMFNetCredential . Si l’utilisateur doit être invité (indiqué par l’indicateur REQUIRE_PROMPT ), la méthode appelle MFPutWorkItem pour mettre en file d’attente un nouvel élément de travail :
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;
}
Le thread de file d’attente de travail appelle Invoke, qui invite l’utilisateur, puis appelle MFInvokeCallback pour appeler le pointeur de rappel fourni dans BeginGetCredentials.
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;
}
La méthode EndGetCredentials termine l’opération en retournant le pointeur IMFNetCredential à l’appelant.
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;
}
Rubriques connexes