goahead 的认证和自定义登陆页面的cookie使用

Author:张继飞

goahead认证,允许下面几种方式。

NONE - the URL page cannot be accessed.
FULL - the URL can always be accessed, without authentication.
BASIC - BAA is required before the page can be accessed.
DIGEST - DAA is required before the page can be accessed.

在开源代码中的定义分别为
NONE 0
FULL 1
BASIC 2
DIGEST 3

使用认证要通过umconfig.txt文件来分析。
这个文件要与webs可执行程序放在同一目录下。
TABLE=users
ROW=0
name=admin
password=X3Y
group=Administrator
prot=0
disable=0
ROW=1
name=guest
password=M\8
group=Administrator
prot=0
disable=0
TABLE=groups
ROW=0
name=Administrator
priv=4
method=1
prot=0
disable=0
TABLE=access
ROW=0
name=/
method=0
secure=0
group=Administrator

通过um中的代码我们可以知道,认证方式是由TABLE=groups中的method=1控制,然后才是TABLE=access中的method=1,这个method
正好对应上面的四种方式(0-3)(可以自己修改一下就看到了不同)。
下面说一下TABLE=access中的 name=/ 列,这就是具体受限区域,也就是说我们要访问“/”也就是根目录时,便会发出请求认证,
若name=/home.asp时,我们访问其他数据(页面)时,不会出现认证,但访问home.asp时,服务器便会发送请求认证,浏览器弹出
认证页面(当然,我们的method为0或1时不会弹出认证页面)。

认证的好处。服务器发送请求认证后,浏览器通过认证页面进入当前页面后,每访问一个页面都会发送认证:如下:

Authorization: Digest username=”admin”, realm=”GoAhead”, qop=”auth”, algorithm=”MD5”, uri=”/goform/Login”, nonce=”225f1094baa6efcc53957e0750b13c6f”, nc=00000004, cnonce=”f3d9b39f3cacdbc6bf9ce91ef33eb064”, response=”294a765c3dfd501b239cd3d0298db32e”
这样我们就可以通过使用username=”admin”来对某些页面进行设置,对某些用户进行限制,比如某些用户只能访问特定的页面以及
修改特定的功能。

下面就来说说如何使用自定义登录界面login.asp。
可以使用cookie,我们在服务器端添加wp->cookie的具体信息。
我自己写了一个添加和获取cookie的文件,cookie.c和cookie.h,放在与webs.c同目录的主目录下。如下:

#
# cookie.c
#

include “webs.h”

void ws_set_cookie(webs_t wp, char *name, char *value, int min, char *path,
char *pcOthersInTail)
{
int iLen;

/* 1 is the ; and white space before 'others in tail' */
iLen = strlen(name) + strlen(value) + strlen(path) + 2;
if (pcOthersInTail != NULL) 
    iLen += strlen(pcOthersInTail);
else
    pcOthersInTail = "";

if (min)
{
    char acExpireData[64];
    struct tm *pstTm;
    time_t zTime;

    zTime = time(NULL);
    zTime += min * 60;

    pstTm = gmtime(&zTime);
    iLen += strftime(acExpireData, 64, "%A, %d-%m-%Y %H:%M:%S GMT", pstTm);

    if (wp->cookie)
        bfree(B_L, wp->cookie);
    iLen += 20;
    fmtAlloc(&wp->cookie, iLen, "%s=%s; Expires=%s; Path=%s; %s", 
             name, value, acExpireData, path, pcOthersInTail);
}
else
{
    if (wp->cookie)
        bfree(B_L, wp->cookie);
    iLen += 10;
    fmtAlloc(&wp->cookie, iLen, "%s=%s; Path=%s; %s", name, value, path, 
             pcOthersInTail);
} 

websSetRequestFlags(wp, wp->flags | WEBS_COOKIE);

}

void ws_clear_cookie(webs_t wp, char *name, char *path)
{
char acExpireData[64];
struct tm *pstTm;
time_t zTime;

zTime = time(NULL);
zTime -= 60;

pstTm = gmtime(&zTime);
strftime(acExpireData, 64, "%A, %d-%m-%Y %H:%M:%S GMT", pstTm);

websWrite(wp, "Set-Cookie: %s=0; Expires=%s; Path=%s\r\n", name, acExpireData, path);

}

int ws_get_cookie(webs_t wp, char *name, char **ppValue, int *pLen)
{
char *pcStr, *pcTmpStr1, *pcTmpStr2;
unsigned short len, tmpLen1, tmpLen2;

if (!wp->cookie || !(wp->flags & WEBS_COOKIE))
    return 1;

pcStr = wp->cookie;
len = strlen(pcStr);

while (len)
{
    pcTmpStr1 = strchr(pcStr, ';');
    tmpLen1 = (pcTmpStr1) ? pcTmpStr1 - pcStr : len;
    len -= tmpLen1;

    pcTmpStr1 = pcStr;
    pcStr += tmpLen1 + 1;

    /* get the name */
    pcTmpStr2 = strchr(pcTmpStr1, '=');
    if (!pcTmpStr2 || pcTmpStr2 >= pcStr)
        return 1;

    tmpLen2 = pcTmpStr2 - pcTmpStr1;

    /* ignore the whitespace */

    /* get the name */
    if (strncmp(name, pcTmpStr1, tmpLen2))
        continue;        

    /* get the value */
    pcTmpStr1 = pcTmpStr2 + 1;
    tmpLen2 = pcStr - pcTmpStr1 - 1;

    /* ignore the whitespace */

    if (!tmpLen2)
        return 1;

    *ppValue = pcTmpStr1;
    *pLen = tmpLen2;

    return 0;
}

return 1;

}

#
# cookie.h
#

ifndef _h_WS_COOKIE

define _h_WS_COOKIE 1

ifdef __cplusplus

extern”C”{

endif

/* set cookie in path with name, value and expire time */
void ws_set_cookie(webs_t wp, char *name, char *value, int min, char *path,
char *pcOthersInTail);

/* clear cookie in ‘path’ named ‘name’ */
void ws_clear_cookie(webs_t wp, char *name, char *path);

/* get cookie with specific name */
ZINT ws_get_cookie(webs_t wp, char *name, char **ppValue, int *pLen);

ifdef __cplusplus

}

endif

endif

在websResponse()中添加这么段代码,作用是设置cookie字段,往客户端发送。
if (wp->flags & WEBS_COOKIE)
{
websWrite(wp, T(“Set-Cookie: %s\r\n”), wp->cookie);
}

上面已经完成了cookie的设置,下面来实现如何使用cookie,在login页面点登陆后,执行
Login函数时,我们便设置cookie,方法如下:
value = websGetVar(wp, T(“username”), NULL);
……
ws_set_cookie(wp, “username”, value, 0, “/”, NULL);

在每一个受限页面的最顶端添加Web_ChkUser()函数,用来防止没有登录而直接输入地址就能访问页面。
具体代码如下:(这是一个asp定义,而Login函数是个form定义)
int Web_ChkUser(int eid, webs_t wp, int argc, char_t **argv)
{
int iVaild = 0;
int iLen;
char *value;
if (ws_get_cookie(wp, “username”, &value, &iLen) != 0)
{
websWrite(wp, ““);
return -1;
}
/* compare with admin name */
if (gstricmp(value,&administrator[0]) == 0)
{
/* todo sign the user type to admin */
iVaild = 1;
}
else
{
/* compare with user name */
if (gstricmp(value,&guest[0]) == 0)
{
iVaild = 1;
}
}
if (!iVaild)
{
websWrite(wp, ““);
return -1;
}
return 0;
}

后来出现了个问题,由于页面采用层的方式,所以在点提交表单的时候,客户端浏览器发送cookie时,cookie格式为,
Cookie: username=admin; username=admin,这里面带了两个username,经过分析猜测是两个页面同时发送的cookie,因为当前页面
由两个页面组成。然后修改了一下获取cookie的函数,当发送cookie如上时,只取后面的一个。修改代码如下:

int ws_get_cookie(webs_t wp, char *name, char **ppValue, int *pLen)
{
char *pcStr, *pcTmpStr1, *pcTmpStr2;
unsigned short len, tmpLen1, tmpLen2;
if (!wp->cookie || !(wp->flags & WEBS_COOKIE))
return 1;

pcStr = wp->cookie;
len = strlen(pcStr);

    pcTmpStr1 = strchr(pcStr, ';');
    if(pcTmpStr1)
    {
        pcStr = pcTmpStr1+2;
    }

    /* get the name */
    pcTmpStr2 = strchr(pcStr, '=');
    if (!pcTmpStr2)
        return 1;

    tmpLen1 = pcTmpStr2 - pcStr;

    /* ignore the whitespace */

    /* get the name */
    if (strncmp(name, pcStr, tmpLen1))
        return 1;

    /* get the value */
    pcTmpStr1 = pcTmpStr2 + 1;
    tmpLen2 = strlen(pcTmpStr1);

    /* ignore the whitespace */

    if (!tmpLen2)
        return 1;

    *ppValue = pcTmpStr1;
    *pLen = tmpLen2;

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值