|
|
Question : ISAPI Authentication Filter
|
|
Hi !
I am trying to code an ISAPI Filter, that does dynamic authentication based on the URL. I code with Delphi, but C++ example/source will do just fine.
Here's what i do: 1. at GetFilterVersion i register with the following flags: SF_NOTIFY_URL_MAP,SF_NOTIFY_AUTHENTICATION,SF_NOTIFY_SECURE_PORT,SF_NOTIFY_NONSECURE_PORT 2. at HttFilterProc i have something like this : a. if Notification Type is SF_NOTIFY_URL_MAP, i cast the pvNotification pointer to a HTTP_FILTER_URL_MAP to obtain the URL and decide weather its a protected URL or not. In case it is protected i do : pFc.ServerSupportFunction(Pfc,SF_REQ_SEND_RESPONSE_HEADER,PChar('401 Authorization Required'),dword(Domain),0) where Domain contains "WWW-Authenticate: Basic realm="Restricted Area" then return SF_STATUS_REQ_NEXT_NOTIFICATION.
b. if Notification Type is SF_NOTIFY_AUTHENTICATION i cast pvNotification to HTTP_FILTER_AUTHENT to obtain user/password supplied. If invalid user/pass i return SF_STATUS_REQ_ERROR otherwise i return SF_STATUS_REQ_HANDLED_NOTIFICATION.
The following is the actual Delphi code (where GlobalURL, user and password variables are global) : case NotificationType of SF_NOTIFY_PREPROC_HEADERS: begin PreprocHeaders := THTTP_FILTER_PREPROC_HEADERS(pvNotification^); BufferSize := SizeOf(Buffer); PreprocHeaders.GetHeader(pfc,'url',Buffer,BufferSize); LogInfo('Notify Preprocess Headers URL: '+Buffer); end; SF_NOTIFY_URL_MAP: begin LogInfo('************ Entering SF_NOTIFY_URL_MAP ************ '); UrlMap := THTTP_FILTER_URL_MAP(pvNotification^); GlobalURL := UrlMap.pszURL; LogInfo('Notify URL Map: '+strpas(UrlMap.pszURL)); if strContains('/noie',GlobalURL) then begin LogInfo('*** Protected URL Detected !'); if (User <> 'someuser') and (pass <> 'somepassword') then begin LogInfo('No user/pass supplied ... sending auth headers !'); Domain := 'WWW-Authenticate: Basic realm="Restricted Area"'; pFc.ServerSupportFunction(Pfc,SF_REQ_SEND_RESPONSE_HEADER,PChar('401 Authorization Required'),dword(Domain),0); SizeBuf:= 20; pfc.WriteClient(pfc,pchar('Password protected !'),SizeBuf,0); Result := SF_STATUS_REQ_NEXT_NOTIFICATION; end else begin LogInfo('Correct user/pass'); LogInfo('User: '+User); LogInfo('Pass: '+Pass); Result := SF_STATUS_REQ_HANDLED_NOTIFICATION; end; end else Result := SF_STATUS_REQ_NEXT_NOTIFICATION;
LogInfo('************ Exiting SF_NOTIFY_URL_MAP ************ '); end; SF_NOTIFY_AUTHENTICATION: begin LogInfo('************ Entering SF_NOTIFY_AUTHENTICATION ************ '); if User = 'someuser' then begin Result := SF_STATUS_REQ_HANDLED_NOTIFICATION; end else begin AuthHeader := THTTP_FILTER_AUTHENT(pvNotification^); LogInfo('Notify Authentication: '+GlobalURL); User := AuthHeader.pszUser; Pass := AuthHeader.pszPassword; LogInfo('Notify Authentication User: '+User); LogInfo('Notify Authentication Pass: '+Pass); if user<>'someuser' then begin LogInfo('Sending auth ...'); Domain := 'WWW-Authenticate: Basic realm="Restricted Area"'; pFc.ServerSupportFunction(Pfc,SF_REQ_SEND_RESPONSE_HEADER,PChar('401 Authorization Required'),dword(Domain),0); SizeBuf:= 20; pfc.WriteClient(pfc,pchar('Password protected !'),SizeBuf,0); Result := SF_STATUS_REQ_ERROR; end else begin User := AuthHeader.pszUser; Pass := AuthHeader.pszPassword; LogInfo('Correct user/pass found in SF_NOTIFY_AUTHENTICATION !'); Result := SF_STATUS_REQ_HANDLED_NOTIFICATION; end; end; LogInfo('************ Exiting SF_NOTIFY_AUTHENTICATION ************ '); end; end;
The thing is that even when the log says that correct user/pass are found, i still get the login window asking username and password. Does anybody has any ideea what's wrong, or how can i do it right ?
|
Answer : ISAPI Authentication Filter
|
|
In C++ code:
// function that corresponds to your SF_NOTIFY_AUTHENTICATION switch case DWORD CLoginFilter::OnAuthentication(CHttpFilterContext* pCtxt, PHTTP_FILTER_AUTHENT pAuthent) {
... // code that checks permitions and retrieves a valid NT username and password into m_strUsername and m_strPassword. // this can be a database query or what ever... // Example: Query = " select txt_nt_login, txt_nt_password from users where "; Query += " users.txt_login = '"; Query += dbQuoteEscape(pAuthent->pszUser); Query += "' AND users.txt_password = '"; QUery += dbQuoteEscape(pAuthent->pszPassword)+"'";
...
if (bAuthenticated) { strcpy(pAuthent->pszUser, LPCTSTR(m_strUsername)); strcpy(pAuthent->pszPassword, LPCTSTR(m_strPassword)); return SF_STATUS_REQ_HANDLED_NOTIFICATION; } else { // clear the given login and password for security memset(pAuthent->pszUser, '\0', strlen(pAuthent->pszUser)); memset(pAuthent->pszPassword, '\0', strlen(pAuthent->pszPassword)); return SF_STATUS_REQ_NEXT_NOTIFICATION; }
|
|
|
|
|