मैं वर्तमान में माइक्रोसॉफ्ट HTTP सर्वर एपीआई संस्करण 2.0 (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364510(v=vs.85).aspx) का उपयोग कर एक छोटा HTTP सर्वर लागू कर रहा हूं।माइक्रोसॉफ्ट HTTP सर्वर एपीआई - एसएसएल का उपयोग, ग्राहक प्रमाण पत्र की मांग कैसे करें?
मुझे सर्वर पक्ष पर HTTPS को सक्षम करने की आवश्यकता है और क्लाइंट अनुरोध आने पर क्लाइंट प्रमाणपत्र की भी आवश्यकता है (मुझे क्लाइंट को प्रमाणित करने के लिए क्लाइंट को प्रमाणित करने के लिए क्लाइंट की आवश्यकता है और क्लाइंट को प्रमाणीकृत करने के लिए सर्वर और उन्हें एसएसएल पर संवाद करना चाहिए)।
अब तक मैं सर्वर-साइड एसएसएल सक्षम करने में सक्षम हूं, इसलिए मैं सुरक्षित रूप से {https://127.0.0.1:9999/hello} साइट से कनेक्ट कर सकता हूं, सर्वर से अनुरोध कर सकता हूं और प्रतिक्रिया प्राप्त कर सकता हूं, लेकिन मैं सुविधा को चालू करने में सक्षम नहीं हूं जो ग्राहक प्रमाण पत्र के साथ-साथ अनुरोध करता है (और इसे सत्यापित करता है)।
मैं अपने आवेदन कोड में कहा कि मैं सुन रहा हूँ "{https://127.0.0.1:9999/hello}" URL (यह URL मैं यूआरएल समूह में जोड़ा था) और फिर मैं SSL के लिए 9999 पोर्ट बाध्य करने के लिए Netsh.exe उपकरण का उपयोग किया:
C:\>netsh http add sslcert ipport=0.0.0.0:9999 certhash=e515b6512e92f4663252eac72c28a784f2d78c6 appid={2C565242-B238-11D3-442D-0008C779D776} clientcertnegotiation=enable
मुझे यकीन नहीं है कि यह "क्लाइंटक्रर्टनेगोएशन = सक्षम" वास्तव में क्या करना चाहिए, दस्तावेज़ों ने कहा कि इसे "प्रमाण पत्र की बातचीत चालू करनी चाहिए"। तो अब मैं अपने HTTP सर्वर कोड को एक अतिरिक्त समारोह कॉल कहा:
DWORD answer = 0;
HTTP_SSL_CLIENT_CERT_INFO sslClientCertInfo;
ULONG bytesReceived;
answer = HttpReceiveClientCertificate(hReqQueue, pRequest->ConnectionId, 0,
&sslClientCertInfo, sizeof(HTTP_SSL_CLIENT_CERT_INFO), &bytesReceived, NULL);
मैं समझ गया अब क्लाइंट प्रमाणपत्र के लिए संकेत दिया जाना चाहिए कि है, लेकिन यह काम नहीं करता है (मैं शायद, कुछ गलत कर रहा हूँ ताकि है कारण मैं यहां अपना प्रश्न लिख रहा हूं)। "उत्तर" का मान 1168 (ERROR_NOT_FOUND) है। मैं एक क्लाइंट के रूप में फ़ायरफ़ॉक्स ब्राउज़र का उपयोग कर रहा हूं और मैंने वहां एक प्रमाणपत्र जोड़ा है: टूल्स-> विकल्प-> सर्टिफिकेट देखें-> आयात करें, इसलिए फ़ायरफ़ॉक्स शायद उस प्रमाणपत्र का उपयोग कर सकता है या कुछ सर्टिफिकेट के लिए प्रॉम्प्ट शायद, लेकिन मुझे संदेह है कि फ़ायरफ़ॉक्स नहीं करता है क्लाइंट प्रमाण पत्र के लिए सर्वर का अनुरोध बिल्कुल प्राप्त नहीं होता है।
किस बिंदु पर HTTP सर्वर क्लाइंट प्रमाणपत्र के लिए पूछना चाहिए? मैंने सोचा कि आने वाले अनुरोध के बाद यह सही होना चाहिए। प्रदर्शित करने के लिए वास्तव में मैं क्या कर रहा हूँ, मैं Microsoft से HTTP सर्वर नमूना अनुप्रयोग कोड (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364640(v=vs.85).aspx) का उपयोग कर रहा हूँ, कि मैं sligthly संशोधित कर लिया है:
#include "precomp.h"
#include <iostream>
//
// Macros.
//
#define INITIALIZE_HTTP_RESPONSE(resp, status, reason) \
do \
{ \
RtlZeroMemory((resp), sizeof(*(resp))); \
(resp)->StatusCode = (status); \
(resp)->pReason = (reason); \
(resp)->ReasonLength = (USHORT) strlen(reason); \
} while (FALSE)
#define ADD_KNOWN_HEADER(Response, HeaderId, RawValue) \
do \
{ \
(Response).Headers.KnownHeaders[(HeaderId)].pRawValue = \
(RawValue);\
(Response).Headers.KnownHeaders[(HeaderId)].RawValueLength = \
(USHORT) strlen(RawValue); \
} while(FALSE)
#define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb))
#define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr))
//
// Prototypes.
//
DWORD DoReceiveRequests(HANDLE hReqQueue);
DWORD SendHttpResponse(HANDLE hReqQueue, PHTTP_REQUEST pRequest, USHORT StatusCode, PSTR pReason, PSTR pEntity);
DWORD SendHttpPostResponse(HANDLE hReqQueue, PHTTP_REQUEST pRequest);
/*******************************************************************++
Routine Description:
main routine
Arguments:
argc - # of command line arguments.
argv - Arguments.
Return Value:
Success/Failure
--*******************************************************************/
int __cdecl wmain(int argc, wchar_t * argv[])
{
ULONG retCode;
HANDLE hReqQueue = NULL; //request queue handle
int UrlAdded = 0;
HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_2;
retCode = HttpInitialize(
HttpApiVersion,
HTTP_INITIALIZE_SERVER ,
NULL
);
if (retCode == NO_ERROR)
{
// If intialize succeeded, create server session
HTTP_SERVER_SESSION_ID serverSessionId = NULL;
retCode = HttpCreateServerSession(HttpApiVersion, &serverSessionId, 0);
if (retCode == NO_ERROR)
{
// server session creation succeeded
//create request queue
retCode = HttpCreateRequestQueue(HttpApiVersion, NULL, NULL, 0, &hReqQueue);
if (retCode == NO_ERROR)
{
//create the URL group
HTTP_URL_GROUP_ID urlGroupId = NULL;
retCode = HttpCreateUrlGroup(serverSessionId, &urlGroupId, 0);
if (retCode == NO_ERROR)
{
retCode = HttpAddUrlToUrlGroup(urlGroupId, L"https://127.0.0.1:9999/hello", 0, 0);
if (retCode == NO_ERROR)
{
//Set url group properties
//First let's set the binding property:
HTTP_BINDING_INFO bindingInfo;
bindingInfo.RequestQueueHandle = hReqQueue;
HTTP_PROPERTY_FLAGS propertyFlags;
propertyFlags.Present = 1;
bindingInfo.Flags = propertyFlags;
retCode = HttpSetUrlGroupProperty(
urlGroupId,
HttpServerBindingProperty,
&bindingInfo,
sizeof(HTTP_BINDING_INFO));
DoReceiveRequests(hReqQueue);
}
HttpCloseUrlGroup(urlGroupId);
}//if HttpCreateUrlGroup succeeded
HttpCloseRequestQueue(hReqQueue);
}//if HttpCreateRequestQueue succeeded
HttpCloseServerSession(serverSessionId);
} // if HttpCreateServerSession succeeded
HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
}// if httpInialize succeeded
return retCode;
}//main
/*******************************************************************++
Routine Description:
The function to receive a request. This function calls the
corresponding function to handle the response.
Arguments:
hReqQueue - Handle to the request queue
Return Value:
Success/Failure.
--*******************************************************************/
DWORD DoReceiveRequests(IN HANDLE hReqQueue)
{
ULONG result;
HTTP_REQUEST_ID requestId;
DWORD bytesRead;
PHTTP_REQUEST pRequest;
PCHAR pRequestBuffer;
ULONG RequestBufferLength;
//
// Allocate a 2 KB buffer. This size should work for most
// requests. The buffer size can be increased if required. Space
// is also required for an HTTP_REQUEST structure.
//
RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
pRequestBuffer = (PCHAR) ALLOC_MEM(RequestBufferLength);
if (pRequestBuffer == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
pRequest = (PHTTP_REQUEST)pRequestBuffer;
//
// Wait for a new request. This is indicated by a NULL
// request ID.
//
HTTP_SET_NULL_ID(&requestId);
for(;;)
{
RtlZeroMemory(pRequest, RequestBufferLength);
result = HttpReceiveHttpRequest(
hReqQueue, // Req Queue
requestId, // Req ID
0, // Flags
pRequest, // HTTP request buffer
RequestBufferLength,// req buffer length
&bytesRead, // bytes received
NULL // LPOVERLAPPED
);
if(NO_ERROR == result)
{
DWORD answer = 0;
HTTP_SSL_CLIENT_CERT_INFO sslClientCertInfo;
ULONG bytesReceived;
answer = HttpReceiveClientCertificate(hReqQueue, pRequest->ConnectionId, 0,
&sslClientCertInfo, sizeof(HTTP_SSL_CLIENT_CERT_INFO), &bytesReceived, NULL);
if (answer != NO_ERROR)
{
result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", "Unauthorized request");
}
else
{
result = SendHttpResponse(hReqQueue, pRequest, 200, "OK", "OK");
}
if (result != NO_ERROR)
{
break; //if failed to send response, stop listening for further incoming requests
}
//
// Reset the Request ID to handle the next request.
//
HTTP_SET_NULL_ID(&requestId);
}
else
{
break;
}
}
if(pRequestBuffer)
{
FREE_MEM(pRequestBuffer);
}
return result;
}
/*******************************************************************++
Routine Description:
The routine sends a HTTP response
Arguments:
hReqQueue - Handle to the request queue
pRequest - The parsed HTTP request
StatusCode - Response Status Code
pReason - Response reason phrase
pEntityString - Response entity body
Return Value:
Success/Failure.
--*******************************************************************/
DWORD SendHttpResponse(
IN HANDLE hReqQueue,
IN PHTTP_REQUEST pRequest,
IN USHORT StatusCode,
IN PSTR pReason,
IN PSTR pEntityString
)
{
HTTP_RESPONSE response;
HTTP_DATA_CHUNK dataChunk;
DWORD result;
DWORD bytesSent;
INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason);
ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
if(pEntityString)
{
//
// Add an entity chunk.
//
dataChunk.DataChunkType = HttpDataChunkFromMemory;
dataChunk.FromMemory.pBuffer = pEntityString;
dataChunk.FromMemory.BufferLength =
(ULONG) strlen(pEntityString);
response.EntityChunkCount = 1;
response.pEntityChunks = &dataChunk;
}
result = HttpSendHttpResponse(
hReqQueue, // ReqQueueHandle
pRequest->RequestId, // Request ID
0, // Flags
&response, // HTTP response
NULL, // pReserved1
&bytesSent, // bytes sent (OPTIONAL)
NULL, // pReserved2 (must be NULL)
0, // Reserved3 (must be 0)
NULL, // LPOVERLAPPED(OPTIONAL)
NULL // pReserved4 (must be NULL)
);
if(result != NO_ERROR)
{
wprintf(L"HttpSendHttpResponse failed with %lu \n", result);
}
return result;
}
तो मेरे सवाल का, मैं कैसे सुविधा को सक्षम कर सकता है कि क्लाइंट सर्टिफिकेट की आवश्यकता है और मुझे प्राप्त होने के बाद मैं प्रमाण पत्र कैसे सत्यापित करूं (वर्तमान नमूना कोड केवल क्लाइंट से प्रमाण पत्र प्राप्त करने का प्रयास करता है, सत्यापन भाग गुम है)? मुझे वास्तव में इंटरनेट से कोई नमूने नहीं मिला है जो Microsoft HTTP सर्वर API का उपयोग करता है और क्लाइंट प्रमाणपत्रों की आवश्यकता होती है।
सभी पहले से ही धन्यवाद।
हाय liismai, आप किसी भी प्रगति की है ? चीयर्स, मैनुअल – Manuel