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

尊重原创:http://zjf30366.blog.163.com/blog/static/4111645820095305333730/

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;

}

你可能感兴趣的:(goahead 的认证和自定义登陆页面的cookie使用)