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, "<script language=\"javascript\">location='/login.asp'</script>");
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, "<script language=\"javascript\">location='/login.asp'</script>");
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;
}