在搭建trac/svn系统时,一般都会采用apache的.htacces 认证方法 但trac本身并不提供修改密码的功能,修改密码只能通过htpasswd/htpasswd2命令来进行,这的确是一件相当不make sense的事。
其实,利用一个免费的perl脚本可以方便的通过http方式修改apache的认证文件。
文件名:htpasswd.pl,获取地址http://home.xnet.com/~efflandt/pub/htpasswd.pl
该脚本可以通过web浏览器从你的htpasswd文件直接增加或者删除用户,管理者密码是经过加密的。该脚本本身并不保护一个目录,也不创建一个口令保护功能。它仅用来帮助你管理你的口令文件。这就是说在你的服务器上事先应有口令文件时,该脚本方可发挥作用。
安装&配置
step1.拷贝htpasswd.pl至cgi-bin目录
suse对应/srv/www/cgi-bin
fedora对应/var/www/cgi-bin
step2.改名
把htpasswd.pl改名为htpasswd.cgi
step3.用文本编辑器打开配置脚本(cfg.pl)
编辑如下变量:
#!/usr/local/bin/perl 修改为 #!/bin/perl
配置要修改的apache认证文件,找到以下几行
# Password file with full system path (where not accessible by URL).
$file = '/full_path_to/.htpasswd'; 修改为 $file='/etc/svn-auth-file'#假设你的验证文件是/etc/svn-auth-file
step4 chmod 755 htpasswd.cgi
不出意外的话,访问http://localhost/cgi-bin/htpasswd.cgi即可出现密码修改页面
有关密码文件创建,请参见 http://blog.youkuaiyun.com/forlinux/archive/2006/06/11/787703.aspx
-----htpasswd.pl-------
其实,利用一个免费的perl脚本可以方便的通过http方式修改apache的认证文件。
文件名:htpasswd.pl,获取地址http://home.xnet.com/~efflandt/pub/htpasswd.pl
该脚本可以通过web浏览器从你的htpasswd文件直接增加或者删除用户,管理者密码是经过加密的。该脚本本身并不保护一个目录,也不创建一个口令保护功能。它仅用来帮助你管理你的口令文件。这就是说在你的服务器上事先应有口令文件时,该脚本方可发挥作用。
安装&配置
step1.拷贝htpasswd.pl至cgi-bin目录
suse对应/srv/www/cgi-bin
fedora对应/var/www/cgi-bin
step2.改名
把htpasswd.pl改名为htpasswd.cgi
step3.用文本编辑器打开配置脚本(cfg.pl)
编辑如下变量:
#!/usr/local/bin/perl 修改为 #!/bin/perl
配置要修改的apache认证文件,找到以下几行
# Password file with full system path (where not accessible by URL).
$file = '/full_path_to/.htpasswd'; 修改为 $file='/etc/svn-auth-file'#假设你的验证文件是/etc/svn-auth-file
step4 chmod 755 htpasswd.cgi
不出意外的话,访问http://localhost/cgi-bin/htpasswd.cgi即可出现密码修改页面
有关密码文件创建,请参见 http://blog.youkuaiyun.com/forlinux/archive/2006/06/11/787703.aspx
-----htpasswd.pl-------
#!/usr/local/bin/perl-T
#htpasswd.cgibyDavidEfflandt(efflandt@xnet.com)8/97
#Lastupdate10/4/99
#
#Updatepasswordfilefromthewebforusewithuserauthentication.
#Storeseachlineintheformat:username:crypted_password
#
#Built-informisprovidedifyouGETthescript.
#FormisprocessedifyouPOSTtothisscript.
#
#Ifyouwantyourpasswordstobesecure,itisbesttorunthis
#suidasyou(chmod4705htpasswd.cgi)whichmayrequireCwrapper.
#Alsokeepthisscriptinadirectorythatrequiresuserauthentication
#unlessyouallownewuserstosettheirownpassword(see$allow_new).
#
#Ifnotrunningsuidyoushouldtouchthepasswordfilefirstand
#chmod606(orwhateverisreq'dtoaccessitasyouandwebserver).
#
#Toaddorremoveusersbyanadministrator,createausercalled'admin'
#withapassword.Enterusernameyouwanttoaddorremovewithadmin
#passwordas"CurrentPassword"(plusnewpasswordsfornewusers).
#
#Anyonemayremovetheirownnamefromthepasswordfileiftheysupply
#theircorrectpassword.
###Variables
#Passwordfilewithfullsystempath(wherenotaccessiblebyURL).
$file='/full_path_to/.htpasswd';
#Allowanyonetoaddnewusers(1=yes,0=no)
$allow_new=0;
#Setuntaintedpathforsuidscripts
$ENV{PATH}='/bin:/usr/bin:/usr/local/bin';
$ENV{IFS}=""if$ENV{IFS}ne"";
###EndofVariables
#CreateformandexitonGET
&make_formunless($ENV{'REQUEST_METHOD'}eq"POST");
#GetPOSTinput
read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
#Splitthename-valuepairs
@pairs=split(/&/,$buffer);
foreach$pair(@pairs)
{
($name,$value)=split(/=/,$pair);
$value=~tr/+//;
$value=~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$name=~tr/+//;
$name=~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$FORM{$name}=$value;
}
if($FORM{user}){
$user=$FORM{user};
}else{
&error("Error","Usernamemissingfromform.");
}
$pwd=$FORM{old};
$command=$FORM{command};
unless(($commandeq'remove')
||($FORM{new}&&$FORM{new}eq$FORM{new2})){
&error("PasswordMismatch","Newpasswordmismatchormissing.");
}
#Getexistingpasswords
if(-e$file){
open(IN,$file)or&error("Error","Can'topenpasswordfile:$!");
flock(IN,2);
seek(IN,0,0);
while(<IN>){
chomp;
($name,$value,$tail)=split(/:/,$_,3);
$hash{$name}=$value;
$tail{$name}=$tail;#maintainanyadditionalfields
}
closeIN;
}
#Saltforcrypt
@range=('0'..'9','a'..'z','A'..'Z','.','/');
srand(time()^($$+($$<<15)));
$salt=$range[rand(int($#range)+1)].$range[rand(int($#range)+1)];
#Checkforvalidpasswordorexistinguser
$pass=$hash{$user}if$hash{$user};
$cpwd=crypt($pwd,$pass);
$admin=$hash{admin}&&crypt($pwd,$hash{admin})eq$hash{admin};
if(($commandne'new')&&($admin||$pass&&$cpwdeq$pass)){
if($commandeq'remove'){
delete($hash{$user});delete($tail{$user});
$msg="User<B>$user</B>wasremovedfrompasswordfile.";
}elsif(!$pass){
$msg="WARNING!'ChangePassword'checkedfornon-existinguser?\n"
."<P>Assigningpasswordfornewuser<B>$user</B>anyway.\n"
."<P>Ifthiswasanerror,gobackand'RemoveUser'";
}else{
$msg="Passwordhasbeenupdatedfor$user.";
}
}elsif($FORM{command}eq'new'){
if($pass){
&error("Sorry","User<B>$user</B>isalreadyassigned.");
}elsif($allow_new||$admin){
$msg="Passwordhasbeenassignedfornewuser$user.";
}else{
&begin_html("Sorry,NewUser");
print"Contactfileownerforpasswordyoucanchangelater.";
&end_html;
exit;
}
}else{
&error("PasswordError",
"Invaliduserorpasswordorforgottocheck'NewUser'.");
}
#Assignnewpasswordtouserandwritetofile
$hash{$user}=crypt($FORM{new},$salt)if$commandne'remove';
if(open(OUT,">$file")){
flock(OUT,2);
seek(OUT,0,0);
foreach$name(sortkeys%hash){
printOUT"$name:$hash{$name}";
printOUT":$tail{$name}"if$tail{$name};
printOUT"\n";
}
}else{
&error("Error","Can'tupdatepasswordfile:$!");
}
#PrintReturnHTML
&begin_html("ThankYou");
print"$msg\n";
&end_html;
###Subroutines
#subroutinebegin_html(title)
subbegin_html{
local($title)=@_;
print"Content-type:text/html\n\n";
print"<html><head><title>$title</title></head><body>\n";
print"<center><h1>$title</h1></center>\n<hr><p>\n";
}
#subroutineend_html
subend_html{
#Addfooterlinkshere
print"<P></body></html>\n";
}
#subroutinemake_form
submake_form{
&begin_html("ChangeorAddPassword");
print<<NEW_FORM;
Usethisformtochangeyourpasswordforaccesstorestricted
directorieshere.Newuserswillbeinformedifpasswordwasassignedor
iftheyneedtocontacttheownerofthesepages.
<FORMMETHOD="POST"ACTION="$ENV{SCRIPT_NAME}">
<DL>
<DT>E-mailAddress(orusernameonthissystem):
<DD><INPUTNAME="user">
<DT>CurrentPassword(requiredunlessnewuser):
<DD><INPUTTYPE=PASSWORDNAME="old">
<DT>NewPassword:
<DD><INPUTTYPE=PASSWORDNAME="new">
<DT>ConfirmNewPassword:
<DD><INPUTTYPE=PASSWORDNAME="new2">
<DT>Request:
<DD>
<INPUTTYPE="radio"NAME="command"VALUE="change"CHECKED>ChangePassword
<DD>
<INPUTTYPE="radio"NAME="command"VALUE="new">NewUser
<DD>
<INPUTTYPE="radio"NAME="command"VALUE="remove">RemoveUser
</DL>
<P><INPUTTYPE="submit"VALUE="SubmitRequest">
</FORM>
NEW_FORM
&end_html;
exit;
}
suberror{
local($title,$msg)=@_;
&begin_html($title);
print"<P>$msg\n";
print"<P>Pleasecheckyournameandre-enterpasswords.\n";
&end_html;
exit;
}