• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

SQUID的ncsa_auth认证原理

发布: 2007-5-25 23:53 | 作者: 未知 | 来源: ChinaUnix.net | 查看: 101次 | 进入软件测试论坛讨论

领测软件测试网
前天看了一下ncsa_auth认证程序的源码,发现这个认证其实是非常简单的。
squid启动时运行ncsa_auth passwd密码文件

如果你的认证用户不是很多的话,写个sh就可以解决问题了
ncsa_auth.sh

内容如下
#认证用户名为abc密码123
[code:1:e0e520c5be]
while true ; do
 read a
 user=`echo a| /usr/bin/cut -d ' ' -f1`
 pass=`echo a|/usr/bin/cut -d ' ' -f2`
 if [ "$user" == "abc" ] ; then
         if [ "$pass" == "123" ] ; then
                    echo OK;
        else
                    echo ERR;
        fi
 else
         echo ERR
  fi
done
#结束

呵呵,如果你的认证不是很频繁的话。但是你希望与你的数据库认证集成在一起的话
你也可以用php连结数据库达到这个目的
在ncsa_auth.sh里的内容应该如下:
/usr/local/bin/php /usr/local/etc/ncsa_auth.php

在ncsa_auth.php内容
<?php

$fd = fopen('php://stdin', 'r'); 
while(true){
        $buffer = fgets($fd, 4096);
        $lsstr=explode(' ',$buffer);
        $sql_str="select user from bbs_user where userid like '$lsstr[0]' and pass like '$lsstr[1]'";
        #如果用户名与密码正确的话
         if(true) echo 'OK';
         else echo 'ERR';
}
?>
[/code:1:e0e520c5be]
抛砖引玉,希望大家在用squid认证能够有所启发,当然如果你觉得效率低下的话就使用C,直接修改squid自带的ncsa_auth.c加了数据库查询语句就行了。

 ljily000 回复于:2005-03-06 21:11:31
:em27: 

顶!
Good!

 段誉 回复于:2005-03-12 04:00:37
顶上来,大家都了解一下。

BTW:请大家多多关注我们这个板子,多推荐好帖子,增加我们这个板子的精华数量。谢谢!!

 shitian8848 回复于:2005-03-12 09:32:49
正在弄squid的认证呢,呵呵,谢谢楼主了。
UP!

 platinum 回复于:2005-03-12 10:45:27
请教一下楼主
[code:1:4e08dde378]
while true ; do 
read a 
user=`echo a| /usr/bin/cut -d ' ' -f1` 
pass=`echo a|/usr/bin/cut -d ' ' -f2` 
if [ "$user" == "abc" ] ; then 
        if [ "$pass" == "123" ] ; then 
                   echo OK; 
       else 
                   echo ERR; 
       fi 
else 
        echo ERR 
 fi 
done 
#结束 
[/code:1:4e08dde378]
这个shell用于哪里?
好像和squid认证无关啊~
另外,ncsa的密码是MD5后的,而楼主这个shell是明码

我只是想知道,这个shell是做什么的呢?

 60133056 回复于:2005-03-12 13:45:32
观望 学习

 wingger 回复于:2005-03-12 14:28:08
[quote:7f7046b6b5="platinum"]这个shell用于哪里?
好像和squid认证无关啊~
另外,ncsa的密码是MD5后的,而楼主这个shell是明码

我只是想知道,这个shell是做什么的呢?[/quote:7f7046b6b5]

我也想知道,是用这个来代替ncsa吗?
还是解剖他的原理?

 wxxszzz 回复于:2005-03-12 17:43:24
看了上面大家的回贴,我就再解释一下吧。

我们使用htpasswd产生的那个密码文件里的密码是用MD5加密的。

但是squid传递给ncsa_auth认证程序的密码使用的是明码,
然后由ncsa_auth认证程序再用md5加密传给他的密码后
再与用htpasswd产生的那个密码文件里的密码相比较。
如果符合就认为密码正确。

另外以上的sh与使用php密码认证的程序。
就是接到squid的密码后,不使用md5加密接收到的密码,直接比较,

以上的两个程序
他们都是可以直接替代ncsa_auth这个认证程序的。

OK,如果还有疑问,可以再提问,不过我觉得SQUID他这样的认证是比较合理的。现时也比较直接明了,

设想一下,如果你的认证用户非常多,如有1000人以上同时认证,我们可以简单的使用上面的高级语言如C、php、perl、java等语言,只要他的代码里支持套接字sockets接口你就可以设计一个集中式的认证系统。

以PHP举例:

代码如顶搂的语言里只是稍微修改一下。
[code:1:d8bd213a3b]
在ncsa_auth.php内容 
<?php 

$fd = fopen('php://stdin', 'r'); 
while(true){ 
       $buffer = fgets($fd, 4096); 
       $lsstr=explode(' ',$buffer); 
#这里使用套接字把用户名与密码发送到后台认证中心去
     $sfd=fscoket("x.x.x.x",)
       write      
       read
       fclose($sfd);

fclose($fd);
?> 
[/code:1:d8bd213a3b]
这里之后,一个比较好的认证中心这可以产生了。之所以选用PHP认证,是因为这段时间用PHP比较多。
这样之后,你就可以使用多台SQUID,多台认证中心,一个中央数据库。

呵呵,不知道各位看过我的解释与说明之后,是不是有所启发呢?
没有做不到,只有想不到的事情。

 platinum 回复于:2005-03-16 07:21:21
这个是ncsa_auth.c的源代码
[code:1:2a9999c6f7]
/*
 * ncsa_auth.c
 *
 * AUTHOR: Arjan de Vet <Arjan.deVet@adv.iae.nl>
 *
 * Example authentication program for Squid, based on the original
 * proxy_auth code from client_side.c, written by
 * Jon Thackray <jrmt@uk.gdscorp.com>.
 *
 * Uses a NCSA httpd style password file for authentication with the
 * following improvements suggested by various people:
 *
 * - comment lines are possible and should start with a '#';
 * - empty or blank lines are possible;
 * - extra fields in the password file are ignored; this makes it
 *   possible to use a Unix password file but I do not recommend that.
 *
 */

#include "config.h"
#if HAVE_STDIO_H
#include <stdio.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_CRYPT_H
#include <crypt.h>
#endif

#include "util.h"
#include "hash.h"

static hash_table *hash = NULL;
static HASHFREE my_free;

typedef struct _user_data {
    /* first two items must be same as hash_link */
    char *user;
    struct _user_data *next;
    char *passwd;
} user_data;

static void
my_free(void *p)
{
    user_data *u = p;
    xfree(u->user);
    xfree(u->passwd);
    xfree(u);
}

static void
read_passwd_file(const char *passwdfile)
{
    FILE *f;
    char buf[8192];
    user_data *u;
    char *user;
    char *passwd;
    if (hash != NULL) {
        hashFreeItems(hash, my_free);
    }
    /* initial setup */
    hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
    if (NULL == hash) {
        fprintf(stderr, "ncsa_auth: cannot create hash table\n");
        exit(1);
    }
    f = fopen(passwdfile, "r");
    if (NULL == f) {
        fprintf(stderr, "%s: %s\n", passwdfile, xstrerror());
        exit(1);
    }
    while (fgets(buf, 8192, f) != NULL) {
        if ((buf[0] == '#') || (buf[0] == ' ') || (buf[0] == '\t') ||
            (buf[0] == '\n'))
            continue;
        user = strtok(buf, ":\n\r");
        passwd = strtok(NULL, ":\n\r");
        if ((strlen(user) > 0)  & passwd) {
            u = xmalloc(sizeof(*u));
            u->user = xstrdup(user);
            u->passwd = xstrdup(passwd);
            hash_join(hash, (hash_link *) u);
        }
    }
    fclose(f);
}

int
main(int argc, char **argv)
{
    struct stat sb;
    time_t change_time = 0;
    char buf[256];
    char *user, *passwd, *p;
    user_data *u;
    setbuf(stdout, NULL);
    if (argc != 2) {
        fprintf(stderr, "Usage: ncsa_auth <passwordfile>\n");
        exit(1);
    }
    while (fgets(buf, 256, stdin) != NULL) {
        if ((p = strchr(buf, '\n')) != NULL)
            *p = '\0';          /* strip \n */
        if (stat(argv[1],  sb) == 0) {
            if (sb.st_mtime != change_time) {
                read_passwd_file(argv[1]);
                change_time = sb.st_mtime;
            }
        }
        if ((user = strtok(buf, " ")) == NULL) {
            printf("ERR\n");
            continue;
        }
        if ((passwd = strtok(NULL, "")) == NULL) {
            printf("ERR\n");
            continue;
        }
        rfc1738_unescape(user);
        rfc1738_unescape(passwd);
        u = hash_lookup(hash, user);
        if (u == NULL) {
            printf("ERR\n");
        } else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd))) {
            printf("ERR\n");
        } else {
            printf("OK\n");
        }
    }
    exit(0);
}
[/code:1:2a9999c6f7]
看了一下,关键问题是在这里
[code:1:2a9999c6f7]
        if ((user = strtok(buf, " ")) == NULL) {
            printf("ERR\n");
            continue;
        }
        if ((passwd = strtok(NULL, "")) == NULL) {
            printf("ERR\n");
            continue;
        }
        rfc1738_unescape(user);
        rfc1738_unescape(passwd);
        u = hash_lookup(hash, user);
        if (u == NULL) {
            printf("ERR\n");
        } else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd))) {
            printf("ERR\n");
        } else {
            printf("OK\n");
        }
[/code:1:2a9999c6f7]

如果用ncsa_auth.php来做“认证中心”,squid又怎么去调用呢?

 wxxszzz 回复于:2005-03-16 10:04:32
你没仔细看我项楼的贴子啊.

我写得使用PHP认证是
squid先调用的是ncsa_auth.sh这个文件
也就是在squid.conf这个配置文件写的认证程序为ncsa_auth.sh

而这个ncsa_auth.sh文件的内容就是调用php去执行ncsa_auth.php
ncsa_auth.sh这个文件的内容如下:
[code:1:5cb36057b4]
/usr/local/bin/php /usr/local/squid/etc/ncsa_auth.php
[/code:1:5cb36057b4]
#end
由这个ncsa_auth.sh来调用ncsa_auth.php
这样就可以了啊.
然后再在ncsa_auth.php
里面获得squid传递的用户名与密码.

你仔细研究一下我楼上的那个贴子.
就应该能够明白,如果你告诉我说不懂PHP,那我也无话可说了

 platinum 回复于:2005-03-17 00:42:38
嘿嘿,还真不懂PHP,不过你的原理我是明白了
也可以
[code:1:b068d37ad6]
/bin/bash /xxx/ncsa_auth.sh
[/code:1:b068d37ad6]
这样咯?

也可以多个squid通过一个认证服务器,那个服务器通过PHP+MYSQL进行处理,密码或明或MD5,放到数据库里

如果这样想,自由度真的很大

 yxdyw 回复于:2005-04-04 10:14:42
wxxszzz      
骑士:
 一台ADSL,一台路由器,一台單網卡linux主機,adsl接入路由器,在路由器上面拔號共享上網,我現在在路由器上面開放主機linux,把所有的網關都改為linux主機地址,利用squid+iptables實現透明代理,不知道如何實現,其中如何控制局域網上網?謝謝

 wxxszzz 回复于:2005-04-07 22:54:10
嘿嘿,大概很少有人会这么做吧。

如果三个东东都在一个网段的话,只能实现HTTP透明代理成功。其他的游戏啊QQ阿之类的就不行了。

要实现HTTP,你只要把80端口重定向到SQUID的端口3128端口就行了。


另外一个解决方案就是:

把那台LINUX的网卡再虚拟一块网卡出来,做成两个网段。

其中一个网段跟内网相同。另外一个网段跟路由器相同,当然路由器就只能改成跟linux的网段一样罗。

这样就成为了一个典型的双网卡LINUX路由器了。所有的流量都经过LINUX再通过路由器出去。

至于如何在LINUX下一块网卡绑定两个地址,查查这个论坛的精华吧。

定义好了之后,最简单的透明代理,使用IPTABLES只要三条语名。

[code:1:a7530cf441]
echo 1 >/proc/sys.net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0:1 -s 内网网段 -j MASQUERADE
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to LINUX内网地址:3128
[/code:1:a7530cf441]
OK

延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网