IAuthenticationProvider::SetUser 方法
在身份验证提供程序上设置经过身份验证的用户。
语法
virtual VOID SetUser(
IHttpUser* pUser
) = 0;
parameters
pUser
指向 IHttpUser 的经过身份验证的指针。
备注
pUser
如果 参数为 NULL,则默认身份验证将继续进行。
SetUser
使用非 NULL IHttpUser
指针调用 方法将立即对该用户进行身份验证。
实现者须知
IAuthenticationProvider 实现者负责使用此数据进行内存管理;因此,IAuthenticationProvider
当实现者不再需要 IHttpUser
时,必须调用 IHttpUser::D ereferenceUser 方法。
对调用者的说明
IAuthenticationProvider
调用方负责在调用SetUser
之前在堆上创建自定义IHttpUser
指针;IAuthenticationProvider
然后,实现者承担此new
指针的责任。
示例
下面的代码示例演示如何创建一个 HTTP 模块,该模块允许任何用户通过创建经过身份验证的用户来访问网站。 然后,该示例清除响应标头和正文,并将用户信息返回给客户端。
注意
下面的代码示例通过创建名为 ValidUser
的自定义IHttpUser
指针对所有用户进行身份验证。
#pragma warning( disable : 4290 )
#pragma warning( disable : 4530 )
#define _WINSOCKAPI_
#include <windows.h>
#include <io.h>
#include <sal.h>
#include <httpserv.h>
#include <string>
using namespace std;
#import "msxml6.dll"
using namespace MSXML2;
// The CConvert class mirrors the Convert class that is
// defined in the .NET Framework. It converts primitives
// and other data types to wstring types.
class CConvert
{
public:
// The ToString method converts a HANDLE to a wstring.
// h: the HANDLE to convert to a wstring.
// return: the HANDLE as a wstring.
static wstring ToString(HANDLE h)
{
// If the HANDLE is NULL, return the "NULL" string.
if (NULL == h)
{
return L"NULL";
}
// If the HANDLE is not valid, return
// the INVALID_HANDLE_VALUE as a string.
if (INVALID_HANDLE_VALUE == h)
{
return L"INVALID_HANDLE_VALUE";
}
// The HANDLE is valid.
return L"valid";
}
// The ToString method converts a FILETIME pointer to a wstring.
// fileTime: the FILETIME pointer to convert to a wstring.
// return: the FILETIME pointer as a wstring.
static wstring ToString(FILETIME* fileTime)
{
// If fileTime is NULL, return the empty string.
if (NULL == fileTime)
{
return L"NULL";
}
// Convert the FILETIME to a local time, and
// then convert that local time to a wstring.
SYSTEMTIME stUTC;
SYSTEMTIME stLocal;
FileTimeToSystemTime(fileTime, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
// Create a wstring to return. Note: wsprintf
// can be also used. However, it is more difficult
// to handle both UNICODE and non-UNICODE correctly.
wstring timeString =
ToString(stLocal.wMonth) +
wstring(L"/") +
ToString(stLocal.wDay) +
wstring(L"/") +
ToString(stLocal.wYear) +
wstring(L" ") +
ToString(stLocal.wHour) +
wstring(L":") +
ToString(stLocal.wMinute);
// Return the FILETIME data as a wstring.
return timeString;
}
// The ToString method converts a
// ULARGE_INTEGER pointer to a wstring.
// ui: the ULARGE_INTEGER pointer to convert to a string.
// return: the ULARGE_INTEGER pointer as a string.
static wstring ToString(ULARGE_INTEGER* ui)
{
// Return the empty string if the
// ULARGE_INTEGER pointer is NULL.
if (NULL == ui)
{
return L"NULL";
}
// Return the low-order part to a wstring.
return (ToString(ui->LowPart));
}
// The ToString method converts a PCSTR to a wstring.
// pcstr: the PCSTR to convert to a wstring.
// return: the PCSTR as a wstring.
static wstring ToString(PCSTR pcstr)
{
// Return the empty string
// if the PCSTR is NULL.
if (NULL == pcstr)
{
return L"NULL";
}
// Get the length of the string to copy.
size_t length = strlen(pcstr);
// Create a new double-byte character
// array of length plus 1.
wchar_t* newText = new wchar_t[length+1];
// Copy the source into the sink string.
for (size_t i = 0; i < length; ++i)
{
newText[i] = pcstr[i];
}
// Terminate the string with the NULL character.
newText[length] = '\0';
// Get a wstring from the new double-byte string.
wstring wText = newText;
// Call delete on the newText pointer
// and set this pointer to NULL.
delete[] newText;
newText = NULL;
// Return the wstring copy.
return wText;
}
// The ToString method converts a long to a wstring.
// l: the long value to convert to a wstring.
// return: the long as a wstring.
static wstring ToString(long l)
{
WCHAR str[256];
str[0] = '\0';
_ltow_s(l, str, 256, 10);
return str;
}
// The ToString method converts a DWORD to a wstring.
// d: the DWORD value to convert to a wstring.
// return: the DWORD as a wstring.
static wstring ToString(DWORD d)
{
return ToString((long)d);
}
// The ToString method converts an LPCGUID to a wstring.
// guid: the LPCGUID value to convert to a wstring.
// return: The LPCGUID as a wstring; otherwise, L"" if
// guid is NULL.
static wstring ToString(LPCGUID guid)
{
// If the GUID is NULL, return the empty string.
if (NULL == guid)
{
return L"NULL";
}
// Create a WCHAR array to write the GUID to.
WCHAR guidString[256];
// Initialize the zero-based index of the
// guidString to the null-terminating character
// because the StringFromGUID2 may fail.
guidString[0] = '\0';
// Convert the GUID to a string of the form "{...}".
int characters = StringFromGUID2(*guid, guidString, 256);
// Return the guidString as a wstring.
return guidString;
}
// The ToString method converts a BOOL to a wstring.
// b: the BOOL value to convert to a wstring.
// return: L"true" for true; otherwise, L"false" for false.
static wstring ToString(BOOL b)
{
return (b) ? L"true" : L"false";
}
// The ToByteString converts a double-byte
// character string to a single-byte string.
// str: the double-byte string to convert.
// return: a single-byte string copied from str.
static string ToByteString(const wstring& str)
{
// Get the length of the
// double-byte string.
size_t length = str.length();
// Create a temporary char pointer.
char* byteChar = new char[length+1];
byteChar[0] = '\0';
// Copy the double-byte character string
// into the single-byte string.
size_t charsReturned = 0;
wcstombs_s(&charsReturned, byteChar,
length+1, str.c_str(), length+1);
// Create a string to return.
string retString = byteChar;
// Delete the temporary string and
// set that string to NULL.
delete[] byteChar;
byteChar = NULL;
// Return the single-byte string.
return retString;
}
// The ToString method converts a USHORT to a wstring.
// u: the USHORT value to convert to a wstring.
// return: the value of u as a wstring.
static wstring ToString(USHORT u)
{
return (ToString((long)u));
}
// The ToString method converts a
// const BYTE pointer to a wstring.
// bytes: the BYTE pointer to convert.
// return: the value of bytes as a wstring.
static wstring ToString(const BYTE* bytes)
{
return (ToString((PCSTR)bytes));
}
// The ToString method converts
// a PCWSTR to a wstring.
// pcwstr: the PCWSTR to convert.
// return: L"NULL" if the pcwstr
// parameter is NULL; otherwise,
// pcwstr converted to a wstring.
static wstring ToString(PCWSTR pcwstr)
{
// If the pcwstr parameter
// is NULL, return L"NULL".
if (NULL == pcwstr)
{
return L"NULL";
}
// Implicitly convert the
// PCWSTR to a wstring.
return pcwstr;
}
};
// The CResponseWriter class writes
// text to the response stream.
class CResponseWriter
{
public:
// Creates the CResponseWriter class.
// response: the IHttpResponse
// pointer to write to.
// throws: a _com_error exception if
// the IHttpResponse pointer is NULL.
CResponseWriter(IHttpResponse* response)
throw (_com_error)
{
// If the response is NULL,
// throw an exception.
if (NULL == response)
{
ThrowOnFail(E_INVALIDARG);
}
// Set the internal response.
m_response = response;
}
// The destructor for the CResponseWriter
// class. The CResponseWriter method
// sets the IHttpResponse pointer to NULL.
virtual ~CResponseWriter()
{
m_response = NULL;
}
// The Write method writes the
// PCSTR to the response stream.
// pszValue: the PCSTR to write.
// throws: a _com_error if the
// Write method fails.
void Write
(
PCSTR pszValue
) throw (_com_error)
{
// The string must not be
// NULL, and its length must
// be greater than 0.
if ((NULL == pszValue) ||
(strlen(pszValue) < 1))
{
// Throw an invalid argument
// exception.
ThrowOnFail(E_INVALIDARG);
}
// Create a data chunk structure.
HTTP_DATA_CHUNK dataChunk;
// Set the chunk to a chunk in memory.
dataChunk.DataChunkType =
HttpDataChunkFromMemory;
// Set the chunk to
// the pszValue parameter.
dataChunk.FromMemory.pBuffer =
(PVOID)pszValue;
// Set the chunk size
// to the pszValue length.
dataChunk.FromMemory.BufferLength =
(USHORT)strlen(pszValue);
// Declare and initialize OUT
// parameters for the WriteEntityChunks
// method.
DWORD pcbSent = 0;
BOOL pfCompletionExpected = FALSE;
// Write the entity chunks to
// the response stream.
HRESULT hr =
m_response->WriteEntityChunks
(&dataChunk,
1,
FALSE,
FALSE,
&pcbSent,
&pfCompletionExpected);
// Throw an exception if the call
// to WriteEntityChunks is not a
// success.
ThrowOnFail(hr);
}
// The WriteLine method writes a string
// and newline characters to the response steam.
// pszValue: the PCSTR string to write.
// throws: a _com_error if the PCSTR
// or the newline characters are not
// written to the response stream.
void WriteLine
(
PCSTR pszValue
) throw (_com_error)
{
// Try to write the pszValue parameter.
Write(pszValue);
// Try to write the newline characters.
Write("\r\n");
}
// Convenience method that writes a name
// and value pair to the response stream.
// name: the name of the parameter.
// value: the value of the parameter.
// throws: a _com_error exception if
// the response stream is not written.
void WriteLine
(
const wstring& name,
const wstring& value
) throw (_com_error)
{
// Convert the UNICODE strings
// to mutlibyte strings.
string nameMulti =
CConvert::ToByteString(name);
string valueMulti =
CConvert::ToByteString(value);
// Create the string to write.
string writeString =
nameMulti +
string(": ") +
valueMulti;
// Write the line to
// the response stream.
WriteLine(writeString.c_str());
}
// Tests an HRESULT for success.
// hr: the HRESULT value to inspect.
// throws: a _com_error if the HRESULT
// parameter is not S_OK.
static void ThrowOnFail(HRESULT hr)
{
if (FAILED(hr))
{
_com_error ce(hr);
throw ce;
}
}
private:
// Specify the IHttpResponse
// pointer to write to.
IHttpResponse* m_response;
};
// The CHttpUser class implements the interface IHttpUser
// that emulates a user. This class creates a valid user
// with the user name "ValidUser".
class CHttpUser : public IHttpUser
{
public:
// PRE: none.
// POST: sets the internal reference count to 1.
// The CHttpUser method is the public
// constructor for the CHttpUser class.
CHttpUser()
{
m_refs = 1;
}
// The GetRemoteUserName method
// returns the remote name of the user.
// return: L"ValidUser".
virtual PCWSTR GetRemoteUserName(VOID)
{
return L"ValidUser";
}
// The GetUserName method
// returns the name of the user.
// return: L"ValidUser".
virtual PCWSTR GetUserName(VOID)
{
return L"ValidUser";
}
// The GetAuthenticationType method
// returns the authentication type
// for the user.
// return: L"Anonymous".
virtual PCWSTR GetAuthenticationType(VOID)
{
return L"Anonymous";
}
// The GetPassword method returns
// the password for the user. This
// password is empty because Anonymous
// authentication only requires only a
// non-NULL password value.
// return: L"".
virtual PCWSTR GetPassword(VOID)
{
return L"";
}
// The GetImpersonationToken method returns
// the impersonation token for the user.
// return: NULL.
virtual HANDLE GetImpersonationToken(VOID)
{
return NULL;
}
// The GetPrimaryToken method returns
// the primary token for the user.
// return: NULL.
virtual HANDLE GetPrimaryToken(VOID)
{
return NULL;
}
// PRE: none.
// POST: the internal reference
// count is incremented by 1.
// The ReferenceUser method should be called
// when a new reference to a user is accessed.
virtual VOID ReferenceUser(VOID)
{
InterlockedIncrement(&m_refs);
}
// PRE: the internal reference
// count is at least 1.
// POST: decrements the internal reference count
// and deletes this if that count goes to 0.
virtual VOID DereferenceUser(VOID)
{
if (0 == InterlockedDecrement(&m_refs))
{
delete this;
}
}
// The SupportsIsInRole method returns a BOOL
// indicating whether this user supports roles.
// return: FALSE.
virtual BOOL SupportsIsInRole(VOID)
{
return FALSE;
}
// The IsInRole method returns E_NOTIMPL.
// return: E_NOTIMPL.
virtual HRESULT IsInRole
(
IN PCWSTR pszRoleName,
OUT BOOL* pfInRole
)
{
return E_NOTIMPL;
}
// The GetUserVariable method returns NULL.
// return: NULL.
virtual PVOID GetUserVariable
(
IN PCSTR pszVariableName
)
{
return NULL;
}
private:
// The CHttpUser method is the private virtual
// destructor for the CHttpUser class.
virtual ~CHttpUser()
{
}
// Specify an internal value
// for reference counting.
LONG m_refs;
};
// The CUser class is the wrapper
// class for an IHttpUser pointer.
class CUser
{
public:
// Creates the CUser class.
// user: the IHttpUser pointer to reference.
// throws: a _com_error exception if
// the IHttpUser parameter is NULL.
CUser(IHttpUser* user)
throw (_com_error)
{
// Throw an exception if the
// IHttpUser parameter is NULL.
if (NULL == user)
{
_com_error ce(E_INVALIDARG);
throw ce;
}
// Call ReferenceUser, which increments
// the reference count for the user.
user->ReferenceUser();
// Assign the user to m_user.
m_user = user;
}
// The CUser method is the public
// destructor for the CUser class.
// The destructor calls the DereferenceUser
// method on the IHttpUser pointer, and
// sets that pointer to NULL.
virtual ~CUser()
{
// Call DereferenceUser on the m_user private
// data, which decrements the reference count
// on m_user. An IHttpUser will be deleted when
// its reference count goes to 0.
m_user->DereferenceUser();
// Set the m_user data to NULL.
m_user = NULL;
}
// The CreateElement method converts
// the internal IHttpUser pointer and
// descendant data into an XML element.
// doc: the MSXML2::IXMLDOMDocument3Ptr to use
// for creating elements and attributes.
// return: a new IXMLDOMElementPtr pointer.
// throws: a _com_error exception.
MSXML2::IXMLDOMElementPtr CreateElement
(
MSXML2::IXMLDOMDocument3Ptr doc
) const throw (_com_error)
{
// Create a new XML element to return.
MSXML2::IXMLDOMElementPtr userElement =
doc->createElement(L"user");
// Call the GetAuthenticationType
// method on the IHttpUser pointer.
PCWSTR authTypePCWSTR =
m_user->GetAuthenticationType();
// Convert the PCWSTR to a wstring.
wstring authType =
CConvert::ToString(authTypePCWSTR);
// Add an attribute to the
// userElement element.
AddAttribute(L"authType", authType,
userElement, doc);
// Call the GetImpersonationToken
// method on the IHttpUser pointer.
HANDLE impersonationTokenHANDLE =
m_user->GetImpersonationToken();
// Convert the HANDLE to a wstring.
wstring impersonationToken =
CConvert::ToString(impersonationTokenHANDLE);
// Write an attribute to the
// userElement element.
AddAttribute(L"impersonationToken",
impersonationToken,
userElement,
doc);
// Call the GetPassword method
// on the IHttpUser pointer.
PCWSTR passWordPCWSTR =
m_user->GetPassword();
// Convert the PCWSTR to a wstring.
wstring passWord =
CConvert::ToString(passWordPCWSTR);
// Add an attribute to the
// userElement element.
AddAttribute(L"passWord", L"[hidden]",
userElement, doc);
// Call the GetPrimaryToken method
// on the IHttpUser pointer.
HANDLE primaryTokenHANDLE =
m_user->GetPrimaryToken();
// Convert the HANDLE to a wstring.
wstring primaryToken =
CConvert::ToString(primaryTokenHANDLE);
// Add an attribute to the
// userElement element.
AddAttribute(L"primaryToken",
primaryToken,
userElement,
doc);
// Call the GetRemoteUserName method
// on the IHttpUser pointer.
PCWSTR remoteNamePCWSTR =
m_user->GetRemoteUserName();
// Convert the PCWSTR to a wstring.
wstring remoteName =
CConvert::ToString(remoteNamePCWSTR);
// Add an attribute to
// the userElement element.
AddAttribute(L"remoteName", remoteName,
userElement, doc);
// Call the GetUserName method
// on the IHttpUser pointer.
PCWSTR userNamePCWSTR =
m_user->GetUserName();
// Convert the PCWSTR to a wstring.
wstring userName =
CConvert::ToString(userNamePCWSTR);
// Add an attribute to
// the userElement attribute.
AddAttribute(L"userName", userName,
userElement, doc);
// Call the GetUserVariable method
// on the IHttpUser pointer.
PVOID userVariablePVOID =
m_user->GetUserVariable(HTTP_USER_VARIABLE_SID);
// Convert the PVOID to a wstring.
wstring userVariable =
CConvert::ToString(userVariablePVOID);
// Add an attribute to the
// userElement element.
AddAttribute(L"userVariable",
userVariable,
userElement,
doc);
// Call the SupportsIsInRole method
// on the IHttpUser pointer.
BOOL supportsRolesBOOL =
m_user->SupportsIsInRole();
// Convert the BOOL to a wstring.
wstring supportsRoles =
CConvert::ToString(supportsRolesBOOL);
// Add an attribute to the
// userElement element.
AddAttribute(L"supportsRoles",
supportsRoles,
userElement,
doc);
// If the user supports roles, create
// an Unknown role that the user
// should not be a member of.
if (supportsRolesBOOL)
{
// Declare a BOOL for a
// role that is unknown.
BOOL isInRoleBOOL = FALSE;
// Call the IsInRole method
// on the IHttpUser pointer.
HRESULT hr =
m_user->IsInRole(L"Unknown", &isInRoleBOOL);
// Convert the BOOL to a wstring.
wstring isInRole =
CConvert::ToString(isInRoleBOOL);
// Add an attribute to
// the userElement element.
AddAttribute(L"isInRole",
isInRole,
userElement,
doc);
// Convert the HRESULT to a wstring.
wstring isInRoleHresult =
CConvert::ToString(hr);
// Add an attribute to the
// userElement element.
AddAttribute(L"isInRoleCode",
isInRoleHresult,
userElement,
doc);
}
// Return the XML element.
return userElement;
}
protected:
// The AddAttribute method creates a new XML
// attribute and appends it to the element
// parameter.
// name: the name of the attribute.
// text: the text value of the attribute.
// element: the XML element to
// append the new attribute to.
// doc: the XML document to use for
// creating attributes.
// return: a new IXMLDOMAttributePtr.
// throws: a _com_error exception.
static MSXML2::IXMLDOMAttributePtr AddAttribute
(
const wstring& name,
const wstring& text,
MSXML2::IXMLDOMElementPtr element,
MSXML2::IXMLDOMDocument3Ptr doc
) throw (_com_error)
{
// Create an attribute with the name.
MSXML2::IXMLDOMAttributePtr attribute =
doc->createAttribute(name.c_str());
// Set the text of the attribute to the text value.
attribute->text = text.c_str();
// Add the attribute to the passed element.
element->setAttributeNode(attribute);
// Return the new attribute to the caller.
return attribute;
}
private:
// Specify the IHttpUser pointer
// to authenticate and authorize.
IHttpUser* m_user;
};
// The CAuthenticateModule extends the CHttpModule
// class and authenticates requests. The CAuthenticateModule
// class implements the OnAuthenticateRequest and
// OnPostAuthenticateRequest methods and returns
// RQ_NOTIFICATION_FINISH_REQUEST from those methods
// if the user cannot be verified.
class CAuthenticateModule : public CHttpModule
{
public:
// The CAuthenticateModule method is the public
// constructor for the CAuthenticateModule class.
CAuthenticateModule()
{
}
// The CAuthenticateModule method is the public
// destructor for the CAuthenticateModule class.
virtual ~CAuthenticateModule()
{
}
// The OnAuthenticateRequest method authenticates all
// users by simulating Anonymous authentication.
// pHttpContext: the current IHttpContext pointer.
// pProvider: the current IAuthenticationProvider pointer.
// return: RQ_NOTIFICATION_CONTINUE.
virtual
REQUEST_NOTIFICATION_STATUS
OnAuthenticateRequest
(
IN IHttpContext* pHttpContext,
IN OUT IAuthenticationProvider* pProvider
)
{
// Attempt to get the IHttpUser pointer
// from the IHttpContext pointer.
IHttpUser* currentUser =
pHttpContext->GetUser();
// The IHttpUser pointer will be NULL if the
// user has not yet been authenticated.
if (NULL == currentUser)
{
// Create a new custom anonymous user
// that is always authenticated.
CHttpUser* httpUser =
new CHttpUser;
// Set the authenticated user on the
// provider to signal that this user
// is authentated.
pProvider->SetUser(httpUser);
}
// The user should now be authenticated.
return RQ_NOTIFICATION_CONTINUE;
}
// The OnPostAuthenticateRequest method
// overrides the CHttpModule functionality.
// pHttpContext: the current IHttpContext pointer.
// pProvider: the current IHttpEventProvider pointer.
// return: RQ_NOTIFICATION_CONTINUE.
virtual
REQUEST_NOTIFICATION_STATUS
OnPostAuthenticateRequest
(
IN IHttpContext* pHttpContext,
IN OUT IHttpEventProvider* pProvider
)
{
UNREFERENCED_PARAMETER(pHttpContext);
UNREFERENCED_PARAMETER(pProvider);
return RQ_NOTIFICATION_CONTINUE;
}
// The OnSendResponse method handles
// the RQ_SEND_RESPONSE events.
// pHttpContext: the current IHttpContext pointer.
// pProvider: the current IHttpEventProvider pointer.
// return: RQ_NOTIFICATION_CONTINUE.
virtual
REQUEST_NOTIFICATION_STATUS
OnSendResponse
(
IN IHttpContext* pHttpContext,
IN OUT ISendResponseProvider* pProvider
)
{
// Call the UNREFERENCED_PARAMETER macro because
// the ISendResponseProvider is never used.
UNREFERENCED_PARAMETER(pProvider);
// Retrieve the IHttpUser pointer
// from the IHttpContext pointer.
IHttpUser* user = pHttpContext->GetUser();
// Retrieve the IHttpResponse pointer
// from the IHttpContext pointer.
IHttpResponse* response =
pHttpContext->GetResponse();
// Both the user and response must not
// be NULL. The response must be cleared,
// the response's header must be changed,
// and the CUser constructor precondition
// requires a non-NULL IHttpUser pointer.
if ((NULL == user) || (NULL == response))
{
return RQ_NOTIFICATION_CONTINUE;
}
// Create a writer to write to
// the response stream.
CResponseWriter writer(response);
try
{
// Create an IHttpUser pointer wrapper
// that will increment and decrement the
// reference count, and provide writing
// user information to the response.
CUser userWrapper(user);
// Create a new XML document.
MSXML2::IXMLDOMDocument3Ptr
doc(__uuidof(MSXML2::DOMDocument60));
// Get the user XML element from
// the CUser class, and append
// this element to the XML document.
MSXML2::IXMLDOMElementPtr userElement =
userWrapper.CreateElement(doc);
doc->appendChild(userElement);
// Create the string for writing
// the XML to the response stream.
_bstr_t bstrXml = doc->xml;
string xmlString =
"<?xml version=\"1.0\"?>" + bstrXml;
// Reset the header for text/xml so that
// browsers will display the XML correctly.
HRESULT hr =
response->SetHeader(HttpHeaderContentType,
"text/xml",
(USHORT)strlen("text/xml"),
TRUE);
// If the SetHeader method call failed,
// ignore the failure for now. The user
// can run View/Source in a browser for the
// returned text. It is also possible to
// return here, if necessary.
// Clear the response before writing
// the XML data to the response.
response->Clear();
// Write the XML to
// the response stream.
writer.Write(xmlString.c_str());
}
catch (_com_error& ce)
{
// Write the error description
// to the response stream.
_bstr_t description =
ce.Description();
writer.Write(description);
}
// Return the RQ_NOTIFICATION_CONTINUE message.
return RQ_NOTIFICATION_CONTINUE;
}
};
// The CAuthenticateFactory class implements the
// IHttpModuleFactory interface and creates a new
// CAuthenticateModule pointer and registers that
// pointer for authentication events.
class CAuthenticateFactory : public IHttpModuleFactory
{
public:
// The RegisterCHttpModule static method creates
// a new CAuthenticateFactory pointer and sets
// that pointer on the pModuleInfo as a class factory
// by using the SetRequestNotifications method.
// dwServerVersion: the current server version.
// pModuleInfo: the current IHttpModuleRegistrationInfo
// pointer to call the SetRequestNotifications method.
// pGlobalInfo: the current IHttpServer pointer.
// return: the value returned from the
// SetRequestNotifications call on the pModuleInfo pointer.
static HRESULT RegisterCHttpModule
(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo* pModuleInfo,
IHttpServer* pGlobalInfo
)
{
// Create a new CAuthenticateFactory pointer.
CAuthenticateFactory* moduleFactory =
new CAuthenticateFactory;
// Return an out-of-memory error if the
// CAuthenticateFactory pointer is NULL.
if (NULL == moduleFactory)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
// Set the new CAuthenticateFactory pointer to
// receive authentication requests, and the
// response to send out a final response.
HRESULT hr =
pModuleInfo->SetRequestNotifications
(moduleFactory,
RQ_AUTHENTICATE_REQUEST | RQ_SEND_RESPONSE,
0);
// If the call to the SetRequestNotifications method
// failed, return the HRESULT from that call.
if (FAILED(hr))
{
return hr;
}
// Set the priority to the highest so that
// the user will be authenticated immediately.
return pModuleInfo->SetPriorityForRequestNotification
(RQ_AUTHENTICATE_REQUEST,
PRIORITY_ALIAS_FIRST);
}
// The GetHttpModule method creates a new
// CAuthenticateModule pointer and assigns this pointer
// on the dereferenced CHttpModule pointer.
// ppModule: the dereferenced CHttpModule pointer
// that will be a new CAuthenticateModule pointer.
// pAllocator: the optional IModuleAllocator pointer.
// return: ERROR_NOT_ENOUGH_MEMORY if the heap is
// out of memory; otherwise, S_OK.
virtual
HRESULT
GetHttpModule
(
OUT CHttpModule** ppModule,
IN IModuleAllocator* pAllocator
)
{
// Call the UNREFERENCED_PARAMETER macro
// with the IModuleAllocator pointer because
// this parameter is never used.
UNREFERENCED_PARAMETER(pAllocator);
// Create a new CAuthenticateModule pointer
// and set that pointer on the dereferenced
// CHttpModule parameter.
(*ppModule) = new CAuthenticateModule;
// If the dereferenced ppModule pointer
// is NULL, the heap has been exhausted.
if (NULL == (*ppModule))
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
// Return S_OK.
return S_OK;
}
// The Terminate method calls delete on this.
virtual
void
Terminate()
{
delete this;
}
protected:
// The CAuthenticateFactory method is the protected
// constructor for the CAuthenticateFactory class.
CAuthenticateFactory()
{
}
// The CAuthenticateFactory method is
// the protected virtual destructor for
// the CAuthenticateFactory class.
virtual ~CAuthenticateFactory()
{
}
};
// The RegisterModule method is the
// main entry point for the DLL.
// dwServerVersion: the current server version.
// pModuleInfo: the current
// IHttpModuleRegistrationInfo pointer.
// pGlobalInfo: the current IHttpServer pointer.
// return: the value returned by calling the
// CAuthenticateFactory::RegisterCHttpModule method.
HRESULT
__stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo* pModuleInfo,
IHttpServer* pGlobalInfo
)
{
return CAuthenticateFactory::RegisterCHttpModule
(dwServerVersion,
pModuleInfo,
pGlobalInfo);
}
上述代码将类似于以下内容的 XML 写入响应流。
<?xml version="1.0" ?>
<user
userName="ValidUser"
remoteName=" ValidUser"
passWord="[hidden]"
authType="Anonymous"
impersonationToken="NULL"
primaryToken="NULL"
supportsRoles="false"
userVariable="NULL" />
模块必须导出 RegisterModule 函数。 可以通过为项目创建模块定义 (.def) 文件导出此函数,也可以使用 开关编译模块 /EXPORT:RegisterModule
。 有关详细信息,请参阅 演练:使用本机代码创建Request-Level HTTP 模块。
可以选择使用调用约定编译代码, __stdcall (/Gz)
而不是为每个函数显式声明调用约定。
要求
类型 | 说明 |
---|---|
客户端 | - Windows Vista 上的 IIS 7.0 - Windows 7 上的 IIS 7.5 - Windows 8 上的 IIS 8.0 - Windows 10 上的 IIS 10.0 |
服务器 | - Windows Server 2008 上的 IIS 7.0 - Windows Server 2008 R2 上的 IIS 7.5 - Windows Server 2012 上的 IIS 8.0 - Windows Server 2012 R2 上的 IIS 8.5 - Windows Server 2016 上的 IIS 10.0 |
产品 | - IIS 7.0、IIS 7.5、IIS 8.0、IIS 8.5、IIS 10.0 - IIS Express 7.5、IIS Express 8.0、IIS Express 10.0 |
Header | Httpserv.h |
另请参阅
IAuthenticationProvider 接口
CHttpModule 类
CHttpModule::OnAuthenticateRequest 方法