何為HTTP POST?又有何用武之地?

(粤版/香港文字)

HTTP POST其實可以講喺互聨網溝通程序。。。又用户(client)游览器呈報數据到伺服器(server)喥(例如jsp,asp,php以及其它scripting 語言)處,然後輸出某些预設嘅答案。詳细解釋請閱讀rfc2616.pdf文件;此文件非常容易喺互聨網喥搜索得到,尤其喺W3C官方網站。

一般我哋都喺將個HTTP POST運用喺asp-asp,jsp-jsp或asp-jsp網頁溝通程式上。。。啱冇。。。 你有冇想過引用此方案于一般桌面(Desktop)程式上?例如 VB6或VC++咁?

举個例子;如果一個Win32 application需要一個用户驗証登入界面,但問題喺往往喺大機構里面只得總機(伺服器)嘅數据庫先會存有用户嘅資料同登入密碼。

一般人會答:“直接联系嗰數据庫及讀取應要嘅資料咪得囖。。。何必搞到咁腹雜咁麻煩吖。”

啱,如果個方案喺限于一間機構里運作;但萬一喺運作于多間機構于唔同地點呢?喺咁做嘅話,你有冇念過安全嘅問題呢?

也許亦有人答:“通常大機構都有VPN嗎~”

啱,但就一定波及多方面嘅人力資源先能達到预期效果囖。。。

跟住就會有人補充:“不如用WebServices啦!”

答得好;而我想講嘅就喺如何去應用HTTP POST嚟做一個用户登入驗証功能但又唔要用WebServices技術(如下圖)。



呢個方案喺利用Wininet.dll嘅互聨網API函式;而我只需一下幾個API就能達到用户登入驗証功能嘞。

InternetOpen
InternetConnect
HttpOpenRequest
HttpAddRequestHeaders
HttpSendRequest
HttpQueryInfo
InternetQueryDataAvailable
InternetReadFile
InternetCloseHandle


如要知以一上每一個API函式嘅詳细解釋,請参閱MSDN Library為凖。

此實驗分咗两個部分:
1. ASP script用于驗証呈報數据。
2. Win32 VC++程式,用于呈報數据(HTTP POST)到伺服器.


因為個ASP script喺非常简單甚至一睇就明嗰只,所以我亦唔會多解釋。 
 

<%@ Language=VBScript CODEPAGE=65001%>

<%
  
dim userid
  
dim password
  
dim result

  
'// GET THE CURRENT POSTED DATA
  userid = request.form("userid")
  password 
= request.form("password")
 
  
'// VERIFY THE USERID & PASSWORD
  if strcomp(userid, "admin"0<> 0 then
    result 
= "Invalid user id!"
  elseif strcomp(password, "p@ssw0rd"0<> 0 then
    result 
= "Invalid password!"
  else
    result 
= "logon successful!"
  end if

  
'// WRITE THE RESULT
  Response.Write result

  
'// STOP ALL RESPONSE
  Response.End
%
>

 
至于個VC++源代碼就要慝别强調三項:

其一:InternetConnect嘅第二引數就喺個伺服器端IP或多或少URL;當你用此源代碼时就要加倍小心。切記必定要改(如果你嘅伺服器唔喺安装于同開發平台同一部電脑,127.0.0.1也就喺代表localhost)。

其二:HttpOpenRequest嘅第三引數就喺個驗証呈報數据asp script網址。此項也要小心;當你個logon.asp唔係喺eval嘅virtual directory喥;咁就將次换去你設定嘅path嘞。

其三:HttpSendRequest嘅第四引數就喺你所POST嘅資料;亦即喺userid同password。此一定要同asp script里面所冩同一宣告名稱。一旦代諕出錯。。。咁個呈報數据就無法收到嘞。仲有,個POST資料一定要跟以下格式。

useridadmin&password=p@ssw0rd


userid同password喺宣告名稱,而admin同p@ssw0rd就喺個宣告名稱值數。由第二個宣告名稱就要加一個&符諕嚟分開每一個宣告名稱同前一個宣告名稱嘅值數。


當個asp script程式操作完後就會轉回值數;而個Win32 VC++程式就會分析個轉回值數而斷定登入驗証成功或失敗嘞。

實驗源代碼下載: /Files/hackzai/source/vc//httppost_code.zip

 

long PostToRemoteServer (LPBYTE pMessage, LPHTTPINFO lphi, LPBYTE pOutput, int nMaxBuffer)
{
    HTTPINFO        HttpInfo        
= {NULL};
    LPBYTE            lpData            
= NULL;
    
    DWORD            dwSize            
= 0;
    DWORD            dwRet            
= 0;
    DWORD            dwByteRead        
= 0;
    DWORD            dwContentLen    
= 0;
    DWORD            dwByteAvailable 
= 0;

    HINTERNET        hSession        
= NULL;
    HINTERNET        hConnection        
= NULL;
    HINTERNET        hOpenRequest    
= NULL;

    
char            szHeader[]        = "Content-Type: application/x-www-form-urlencoded\r\n";
    
long            lResult            = 0;




    __try
    
{
        
// Ensure the pass in arguement is valid
        if (NULL == lphi)     {return -9;}
        
if (NULL == pOutput) {return -8;}
        
if (0 == nMaxBuffer) {return -7;}


        
// Open a new instance of the Internet Access
        hSession = InternetOpen("CIBS",
                                INTERNET_OPEN_TYPE_PRECONFIG,
                                NULL,
                                NULL,
                                
0);

        
// Checking the Internet session handle
        if (NULL != hSession)
        
{
            
// Connect to the specified server (IP)
            hConnection = InternetConnect(hSession,
                                          CibsInfo.Server,
                                          INTERNET_DEFAULT_HTTP_PORT,
                                          NULL,
                                          
"HTTP/1.1",
                                          INTERNET_SERVICE_HTTP,
                                          
0,
                                          
0);

            
// Check the Internet connect handle value
            if (NULL != hConnection)
            
{
                
// Open a request to the current server
                hOpenRequest = HttpOpenRequest(hConnection,
                                               
"POST",
                                               CibsInfo.WebApp,
                                               
"HTTP/1.1",
                                               NULL,
                                               
0,
                                               INTERNET_FLAG_RELOAD,
                                               
0);

        
                
// Check the OpenRequest handle value
                if (NULL != hOpenRequest)
                
{
                    
// Add the following header type
                    
//        Content-Type: application/x-www-form-urlencoded
                    if (TRUE == HttpAddRequestHeaders (hOpenRequest,
                                                       szHeader,
                                                       strlen(szHeader),
                                                       HTTP_ADDREQ_FLAG_REPLACE 
| HTTP_ADDREQ_FLAG_ADD))
                    
{
                        
// Post the message to server via "POST" method
                        if (TRUE == HttpSendRequest (hOpenRequest,
                                                     NULL,
                                                     
0,
                                                     (LPSTR)pMessage,
                                                     strlen((LPSTR)pMessage)))
                        
{
                            
// Get all the HTTP information
                            dwSize = sizeof(HttpInfo.ContentType);
                            HttpQueryInfo(hOpenRequest, HTTP_QUERY_CONTENT_TYPE,    
&HttpInfo.ContentType,        &dwSize, 0); 
                            dwSize 
= sizeof(HttpInfo.ContentLength);
                            HttpQueryInfo(hOpenRequest, HTTP_QUERY_CONTENT_LENGTH,    
&HttpInfo.ContentLength,    &dwSize, 0); 
                            dwSize 
= sizeof(HttpInfo.LastModified);
                            HttpQueryInfo(hOpenRequest, HTTP_QUERY_LAST_MODIFIED,    
&HttpInfo.LastModified,        &dwSize, 0);   
                            dwSize 
= sizeof(HttpInfo.Server);
                            HttpQueryInfo(hOpenRequest, HTTP_QUERY_SERVER,            
&HttpInfo.Server,            &dwSize, 0);   
                            dwSize 
= sizeof(HttpInfo.StatusCode);
                            HttpQueryInfo(hOpenRequest, HTTP_QUERY_STATUS_CODE,        
&HttpInfo.StatusCode,        &dwSize, 0);  
                            dwSize 
= sizeof(HttpInfo.StatusText);
                            HttpQueryInfo(hOpenRequest, HTTP_QUERY_STATUS_TEXT,        
&HttpInfo.StatusText,        &dwSize, 0);   
                            
// Copy the current data into the output buffer
                            CopyMemory(lphi, &HttpInfo, sizeof(HTTPINFO));

                            
// Reset local variable
                            dwContentLen = 0;
                            
// Reset pass in output buffer
                            memset(pOutput, NULL, nMaxBuffer);

                            
// Continue Query the available data till the EOF
                            
// Where the InternetQueryDataAvailable return FALSE
                            while (InternetQueryDataAvailable(hOpenRequest,
                                                              
&dwByteAvailable,
                                                              
0,
                                                              
0))
                            
{
                                
// Check the current data available download size
                                if (dwByteAvailable > 0)
                                
{
                                    
// Accumulate the data length
                                    dwContentLen += dwByteAvailable;

                                    
// Allocate Memory
                                    lpData = (LPBYTE)LocalAlloc(LPTR, dwByteAvailable+1);
                                    
// Read File
                                    dwRet = InternetReadFile(hOpenRequest, lpData, dwByteAvailable, &dwByteRead);

                                    
// Check current downloaded data agaist pass in buffer size
                                    if (((long)strlen((LPSTR)pOutput) + (long)dwByteAvailable) < nMaxBuffer)
                                    
{
                                        
// Append the current data into the pass in output buffer
                                        strncat((LPSTR)pOutput, (LPSTR)lpData, dwByteAvailable);
                                    }


                                    
// Release the allocate memory
                                    if (NULL != lpData) {LocalFree((LPBYTE)lpData);}
                                    lpData 
= NULL;
                                }

                                
else
                                
{
                                    
// Set Return Value
                                    lResult = (long)dwContentLen;
                                    
// Exit the current WhileWend loop
                                    break;
                                }

                            }

                        }

                        
else
                            
// Set Return Value
                            lResult = -6;
                    }

                    
else
                        
// Set Return Value
                        lResult = -5;
                }

                
else
                    
// Set Return Value
                    lResult = -4;
            }

            
else
                
// Set Return Value
                lResult = -3;
        }

        
else
            
// Set Return Value
            lResult = -2;



        
// Jump top CleanExit section
        goto CleanExit;

    }

    __except(EXCEPTION_EXECUTE_HANDLER)
    
{
        
// PUT YOUR ERROR HANDLE CODE HERE
        

        
// Set the return value
        lResult = -1;
    }


CleanExit:
    
// Close all the used handle
    if(NULL != hOpenRequest)    {InternetCloseHandle(hOpenRequest);}
    
if(NULL != hConnection)    {InternetCloseHandle(hConnection);}
    
if(NULL != hSession)    {InternetCloseHandle(hSession);}


    
// Set default return value
    return lResult;
}
posted on 2005-02-03 22:24  克仔  阅读(2901)  评论(1)    收藏  举报