開発環境はVisualC.NET+SDKです。
WinInetを使ってWebクライアントを作っています。
httpsページを取得しようとしていますが、InternetConnect関数で失敗しています。
どのあたりに間違いがありそうか探しています。何かヒントはありませんか?
コードは以下のように作りました。
void GetDataByInetSSL(void){
HINTERNET hOpen;
HINTERNET hConn;
HINTERNET hInternet;
DWORD dwReadSize;
DWORD dwSize;
HGLOBAL hGBuff;
LPSTR lpszBuff;
char szScheme[256], szServerName[256], szUserName[256], szPassword
[256],szObjectName[256], szExtraInfo[256];
URL_COMPONENTSA UrlComponents;
UrlComponents.dwStructSize = sizeof(URL_COMPONENTSA); //コンポーネント
のサイズ確保
UrlComponents.nScheme = INTERNET_SCHEME_DEFAULT;
UrlComponents.lpszScheme = szScheme; // Schemeの領域
の確保
UrlComponents.dwSchemeLength = sizeof(szScheme);
UrlComponents.lpszHostName = szServerName; // HostNameの領域の確保
UrlComponents.dwHostNameLength = sizeof(szServerName);
UrlComponents.lpszUserName = szUserName; // UserNameの領域の確保
UrlComponents.dwUserNameLength = sizeof(szUserName);
UrlComponents.lpszPassword = szPassword; // Passwordの領域の確保
UrlComponents.dwPasswordLength = sizeof(szPassword);
UrlComponents.lpszUrlPath = szObjectName; // UrlPathの領域の確保
UrlComponents.dwUrlPathLength = sizeof(szObjectName);
UrlComponents.lpszExtraInfo = szExtraInfo; // ExtraInfoの領域の確保
UrlComponents.dwExtraInfoLength = sizeof(szExtraInfo);
InternetCrackUrl(inifiles.url,sizeof
(inifiles.url),ICU_DECODE,&UrlComponents);
hOpen=InternetOpen(INET PROGRAM,
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if(hOpen==false){
DISP(Internet関数に失敗しました);
return;
}
hConn=InternetConnect(hOpen, //Openハンドル
UrlComponents.lpszHostName, //サーバー名
UrlComponents.nPort, //ポート
UrlComponents.lpszUserName, //ユーザー名
UrlComponents.lpszPassword, //ユーザーパスワード
UrlComponents.nScheme, //サービス
0,
0);
if(hConn==false){
InternetCloseHandle(hOpen);
DISP(InternetConnect関数に失敗しました);
return;
}
hInternet=HttpOpenRequest(hConn, //接続
GET, //手法
UrlComponents.lpszUrlPath, //ページ名
HTTP_VERSION, //Version
NULL,
NULL,
INTERNET_FLAG_SECURE, //flags
0);
//読み込みバッファ確保
InternetQueryDataAvailable(hInternet,&dwReadSize,0,0);
hGBuff=GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwReadSize+1);
lpszBuff=(LPSTR)GlobalLock(hGBuff);
while(true){
InternetReadFile(hInternet,lpszBuff,dwReadSize,&dwSize);
if(dwSize==0){
break;
}
lpszBuff[dwSize]='\0';
DISP(lpszBuff);
}
GlobalUnlock(hGBuff);
GlobalFree(hGBuff);
InternetCloseHandle(hInternet);
InternetCloseHandle(hConn);
InternetCloseHandle(hOpen);
}
とりあえず、GetLastError や InternetGetLastResponseInfo で
エラー理由を調べてみるのがよいと思います。
すみません。ちょっと出張中でテストが出来ずレス遅くなりました。
GetLastError()ではエラーコードが87が帰ってきました。
InternetGetLastResponseInfoではうまくエラーメッセージが帰って来ませんでした。
サーバーは自作サーバーでApache+Opensslです。
リダイレクトなどの処理はしていませんので認証、認証の前準備がダメなのだと思いま
す。
どこかに糸口はありませんでしょうか?
Code Description Name
87 The parameter is incorrect. ERROR_INVALID_PARAMETER
InternetCrackUrlの成否判定してないみたいだけど
パラメータエラーなんだから
inifiles.urlに入ってる文字列が変とか、
inifiles.urlがポインタになってsizeofが…とか
そういう理由でInternetCrackUrlで分解失敗してて
InternetConnectも失敗してるとかじゃない?
ん?
InternetConnectの6番目のパラメータ間違ってるじゃん。
ここにいれるのはINTERNET_SCHEME~じゃなくてINTERNET_SERVICEだよ
途中で送っちゃった
で、
INTERNET_SCHEME~にはHTTPSの3ふがあるけど、
INTERNET_SERVICE~には無いからパラメータエラーになってるのかと。
ありがとうございます。上記のようにInternetConnectの関数を
hConn=InternetConnect(hOpen, //Openハンドル
UrlComponents.lpszHostName, //サーバー名
UrlComponents.nPort, //ポート
UrlComponents.lpszUserName, //ユーザー名
UrlComponents.lpszPassword, //ユーザーパスワード
INTERNET_SERVICE_HTTP, //サービス
0,
0);
とすると先に進めるようになりました。
ただこの後に、また問題が出てきたのですが、この後の処理を以下のようにしました。
//---ここから
hInternet=HttpOpenRequest
(hConn,GET,UrlComponents.lpszUrlPath,HTTP_VERSION,",NULL,INTERNET_FLAG_SECURE
,0);
//作成したHTTP要求を発行
bRet=HttpSendRequest(hInternet,NULL, 0,NULL,0);
//----こきまで
この処理でHttpSendRequestが「不明な認証局の認証証」というエラーを返します。
自作のSSLサーバーなのでエラーが出るのは当然なのですがそれが回避できません。
試しにSSLで構築してある一般のサーバーにアクセスした場合は普通にページが取得でき
ました(IEで認証証をGETした後)。
不明な認証局を使う場合のフラッグの設定が悪いのか?と思っています。
もしくはHttpSendRequestに何かオプションを付ける必要があるのでしょうか?
すみません。
認証証の質問については文章を見直すとまとまっていないし、
最初のタイトルからは違った内容になっているので
改めて別の質問として発言を立てます。
一旦この質問は解決済みとします。
新スレがたたないようなので
一応私が実装したものを参考に書いておきます。
>この処理でHttpSendRequestが「不明な認証局の認証証」というエラーを返します。
>自作のSSLサーバーなのでエラーが出るのは当然なのですがそれが回避できません。
正式な認証サーバでないとHttpOpenRequestでは失敗するようです。
なので下記ロジックのようにHttpOpenRequest後にエラーを無視させる
フラグをsetoptionで設定します。
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS;
これでHttpSendRequestがいけると思います。
あとHttpSendRequestなんですが、
ヘッダContent-Type: application/x-www-form-urlencoded
を設定しないとリクエストが飛びません。
なので以下を参考にしてみてください。
hHttpRequest = HttpOpenRequest(
hHttpSession,
POST,
requestFile,
NULL,
NULL,
NULL,
INTERNET_FLAG_SECURE,
0);
if( hHttpRequest == NULL)
{
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}
DWORD dwError = 0;
DWORD dwFlags;
DWORD dwBuffLen = sizeof(dwFlags);
ret = InternetQueryOption (hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
(LPVOID)&dwFlags, &dwBuffLen);
if(ret == FALSE)
{
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS;
ret = InternetSetOption (hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
&dwFlags,
sizeof (dwFlags) );
if(ret == FALSE)
{
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}
CString sHeader;
CString sOption;
char Opt[512];
// ヘッダー生成
sHeader = Content-Type: application/x-www-form-urlencoded;
if(!HttpSendRequest(hHttpRequest, sHeader, sHeader.GetLength(),
(LPVOID)&TEST=777, sizeof(&TEST=777)))
{
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}
まりのちゃんさんありがとうございます
コードを参考にして以下のようにしたら解決しました。
まりのちゃんさんのコードとの違いはリダイレクトの処理とPOSTの処理です。
エラー処理はGoto文で処理してるので省略させて頂いてます。
//---コードここから
//リクエスト作成
hInternet=HttpOpenRequest
(hConn,GET,UrlComponents.lpszUrlPath,HTTP_VERSION,",NULL,INTERNET_FLAG_SECURE
,0);
if(!hInternet){
エラー処理・・・
}
//オプションを設定する
DWORD dwFlags;
DWORD dwFlagsLen=sizeof(dwFlags);
bRet=InternetQueryOption(hInternet, INTERNET_OPTION_SECURITY_FLAGS,
(LPVOID)&dwFlags, &dwFlagsLen);
if(!bRet){
エラー処理・・・
}
dwFlags|=SECURITY_FLAG_IGNORE_UNKNOWN_CA;
dwFlags|=SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
dwFlags|=SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
bRet=InternetSetOption(hInternet,INTERNET_OPTION_SECURITY_FLAGS,
&dwFlags, sizeof(dwFlags));
if(!bRet){
エラー処理・・・
}
//作成したHTTP要求を発行
bRet=HttpSendRequest(hInternet, NULL,0,NULL,0);
if(bRet==FALSE){
エラー処理・・・
}
//---ここまで
ありがとうございました。