65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ISAPI 扩展中使用客户端授权

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.19/5 (18投票s)

2004年8月4日

2分钟阅读

viewsIcon

37650

一篇关于如何在 ISAPI 扩展中使用授权的文章。

引言

通常,ISAPI 扩展在 IIS 引擎成功完成身份验证后才会收到请求。如果存在数据库连接,并且您希望使用用户名和密码作为数据库连接的输入,您将使用 HTML 表单来请求这些信息。为什么不使用标准的浏览器授权对话框呢?因为数据库用户不是有效的 Windows 用户,并且身份验证会失败!好吧,也许可以,但是否不可能使用它呢?不,您必须继续阅读!

背景

在 ISAPI 扩展中,我们搜索 HTTP_AUTHORIZATION 头。如果找不到,我们使用 “HTTP/1.1 401.5 拒绝访问” 拒绝请求。浏览器会提示输入用户名和密码。在客户端向我们发送身份验证信息后,我们可以使用 ISAPI 过滤器捕获 OnAuthentication 事件并将用户名设置回匿名。结果是什么?IIS 引擎将以匿名方式调用我们的扩展,但 HTTP_AUTHORIZATION 头仍然存在,因此我们可以使用它。;o) 太棒了!

过滤器的代码

将此代码放在 OnAuthenticate 方法中,并定义一个常量,其值为您的 ISAPI 扩展 DLL 的名称。为什么?只有在用户调用我们的扩展时才执行此操作。

#define MODULNAME "myextension.dll"
// this is code for the Filter
if(!*pAuthent->pszUser)
{
    //
    //  Tell the server to notify any subsequent
    // notifications in the chain
    //
    return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
// retrieve the URL, so that we can look for our own extension 
char szURL[1024];
DWORD dwSize = sizeof(szURL);
if(pCtxt->GetServerVariable(HEADER_URL, szURL, &dwSize) == TRUE)
{
    if(strstr(_strlwr(szURL), MODULNAME) != 0)
    {
        // it is our own extension
        // clear all for reset to anonymous
        pAuthent->pszUser[0] = pAuthent->pszPassword[0] = '\0';
        return SF_STATUS_REQ_NEXT_NOTIFICATION;
    }
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;

扩展的代码

将此代码放在您的扩展中。只有在用户调用我们的扩展时才执行此操作。为了解码 BASE64 编码的用户名:密码,我使用了在 此处 找到的名为 Base64Coder 的类。

static const TCHAR szAuthRequired[] = _T("HTTP/1.1 401.5 Access Denied\r\n
       WWW-Authenticate: Basic realm=\"my own realm\"\r\nContent-Length: 837\r\n
       Content-Type: text/html\r\n\r\n.....");
// this code for the Extension

CString m_strUserName;
CString m_strPassword;

char szAUTHORIZATION[1024] = "";
DWORD dwSize = sizeof(szAUTHORIZATION);
if(pCtxt->GetServerVariable("HTTP_AUTHORIZATION", 
              szAUTHORIZATION, &dwSize) == TRUE)
{
    if(strstr(szAUTHORIZATION, "Basic ") != NULL)
    {
        char szdecode[1024];
        char szdata[1024];
        char sztmp[1024];
        char *pdest;
        int  pos;
        Base64Coder  Coder;

        strcpy(szdecode, szAUTHORIZATION + 6);
        Coder.Decode(szdecode);
        strcpy(szdata, Coder.DecodedMessage());
        pdest = strstr(szdata, ":");
        pos = pdest - szdata + 1;

        if(pos <= 0)
        {
            SetLastError(ERROR_ACCESS_DENIED);
            pCtxt->m_bSendHeaders = FALSE;
            dwSize = strlen(szAuthRequired);
            pCtxt->WriteClient(szAuthRequired, &dwSize, 0);
        }else
        {
            strcpy(sztmp, szdata);
            sztmp[pos - 1] = '\0';
            m_strUserName = sztmp;
            strcpy(sztmp, szdata + pos);
            m_strPassword = sztmp;
            // now we know the username and the password and 
            // can use it for anything. If the values are not 
            // valid you can post a message or use the code to
            // post a access denied
        }
    }else
    {
        // we only support Basic authorization
    }
}

如果您愿意,可以将过滤器和扩展的代码放在一个 DLL 中。

重要

这仅在启用基本身份验证时才有效。我建议仅将其与 SSL 结合使用,以便加密 IIS 服务器和浏览器之间的通信。

规则

// 
// Copyright (C) 2004 LEAN Software Production
// 
if((this == "nice") || (this == "great")) 
{ 
    pReponse->SetHeader(pfc, (char*) _T("great-stuff:"), (char*) _T("true"));
    return SF_STATUS_REQ_NEXT_NOTIFICATION; 
}else 
{
    CFile::Remove("myextension.dll");
    return SF_STATUS_REQ_ERROR; 
}

请为这篇文章评分! 

历史

  • 版本 1.0 - 准备上传

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.