在搭建gerrit系统时,一般都会采用apache的.htacces 认证方法 但trac本身并不提供修改密码的功能,修改密码只能通过htpasswd/htpasswd2命令来进行,这的确是一件相当不make sense的事。

其实,利用一个免费的perl脚本可以方便的通过http方式修改apache的认证文件。

文件名:htpasswd.pl,获取地址http://home.xnet.com/~efflandt/pub/htpasswd.pl

该脚本可以通过web浏览器从你的htpasswd文件直接增加或者删除用户,管理者密码是经过加密的。该脚本本身并不保护一个目录,也不创建一个口令保护功能。它仅用来帮助你管理你的口令文件。这就是说在你的服务器上事先应有口令文件时,该脚本方可发挥作用。

 

安装&配置


1.拷贝htpasswd.pl至cgi-bin目录

linux对应 /var/www/cgi-bin

suse对应/srv/www/cgi-bin

fedora对应/var/www/cgi-bin

或者放置在例如如/usr/lib 的任意位置,不过需要在apache的配置文件vi /etc/apache2/sites-available/default添加:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

    <Directory "/usr/lib/cgi-bin">

        AllowOverride None

        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch

        Order allow,deny

        Allow from all

    </Directory>


2.改名

把htpasswd.pl改名为htpasswd.cgi

3.用文本编辑器打开配置脚本(cfg.pl)

编辑如下变量:

#!/usr/local/bin/perl 修改为 #!/bin/perl

配置要修改的apache认证文件,找到以下几行

# Password file with full system path (where not accessible by URL).

$file = '/home/gerrit/gerrit.passwd'; 修改为你的验证文件是/etc/apache2/auth-file

step4 chmod 755 htpasswd.cgi 已经配置搭建好apache的话,访问http://localhost/cgi-bin/htpasswd.cgi即可出现密码修改页面 #!/usr/bin/perl  # htpasswd.cgi by David Efflandt (efflandt@xnet.com) 8/97 # Last update 10/4/99 # # Update password file from the web for use with user authentication. # Stores each line in the format: username:crypted_password # # Built-in form is provided if you GET the script. # Form is processed if you POST to this script. # # If you want your passwords to be secure, it is best to run this # suid as you (chmod 4705 htpasswd.cgi) which may require C wrapper. # Also keep this script in a directory that requires user authentication # unless you allow new users to set their own password (see $allow_new). # # If not running suid you should touch the password file first and # chmod 606 (or whatever is req'd to access it as you and webserver). # # To add or remove users by an administrator, create a user called 'admin' # with a password.  Enter username you want to add or remove with admin # password as "Current Password" (plus new passwords for new users). # # Anyone may remove their own name from the password file if they supply # their correct password. ### Variables # Password file with full system path (where not accessible by URL). $file = '/home/gerrit/gerrit.passwd'; # Allow anyone to add new users (1 = yes, 0 = no) $allow_new = 0; # Set untainted path for suid scripts $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{IFS} = "" if $ENV{IFS} ne ""; ### End of Variables # Create form and exit on GET &make_form unless ($ENV{'REQUEST_METHOD'} eq "POST"); # Get POST input read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # Split the name-value pairs @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", "Username missing from form."); } $pwd = $FORM{old}; $command = $FORM{command}; unless (($command eq 'remove')     ||($FORM{new} && $FORM{new} eq $FORM{new2})) {   &error("Password Mismatch", "New password mismatch or missing."); } # Get existing passwords if (-e $file) {   open (IN, $file) or &error("Error", "Can't open password file: $!");   flock(IN,2);   seek(IN,0,0);   while (<IN>) {     chomp;     ($name, $value, $tail) = split(/:/, $_, 3);     $hash{$name} = $value;     $tail{$name} = $tail; # maintain any additional fields   }   close IN; } # Salt for crypt @range = ('0'..'9','a'..'z','A'..'Z','.','/'); srand ( time() ^ ($$ + ($$ << 15)) ); $salt = $range[rand(int($#range)+1)] . $range[rand(int($#range)+1)]; # Check for valid password or existing user $pass = $hash{$user} if $hash{$user}; $cpwd = crypt($pwd, $pass); $admin = $hash{admin} && crypt($pwd, $hash{admin}) eq $hash{admin}; if (($command ne 'new') && ($admin || $pass && $cpwd eq $pass)) {   if ($command eq 'remove') {     delete($hash{$user}); delete($tail{$user});     $msg = "User <B>$user</B> was removed from password file.";   } elsif (!$pass) {     $msg = "WARNING! 'Change Password' checked for non-existing user?\n"     . "<P>Assigning password for new user <B>$user</B> anyway.\n"     . "<P>If this was an error, go back and 'Remove User'";   } else {     $msg = "Password has been updated for $user.";   } } elsif ($FORM{command} eq 'new') {   if ($pass) {     &error("Sorry", "User <B>$user</B> is already assigned.");   }elsif ($allow_new || $admin) {     $msg = "Password has been assigned for new user $user.";   } else {     &begin_html("Sorry, New User");     print "Contact file owner for password you can change later.";     &end_html;     exit;   } } else {   &error("Password Error",     "Invalid user or password or forgot to check 'New User'."); } # Assign new password to user and write to file $hash{$user} = crypt($FORM{new}, $salt) if $command ne 'remove'; if (open(OUT, ">$file")) {   flock(OUT,2);   seek(OUT,0,0);   foreach $name (sort keys %hash) {     print OUT "$name:$hash{$name}";     print OUT ":$tail{$name}" if $tail{$name};     print OUT "\n";   } } else {   &error("Error","Can't update password file: $!"); } # Print Return HTML &begin_html("Thank You"); print "$msg\n"; &end_html; ### Subroutines #subroutine begin_html(title) sub begin_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"; } #subroutine end_html sub end_html { # Add footer links here   print "<P></body></html>\n"; } #subroutine make_form sub make_form {   &begin_html("Change password for Gerrit"); print <<NEW_FORM; Use this form to change your password for access to Gerrit code review system. <FORM METHOD="POST" ACTION="$ENV{SCRIPT_NAME}"> <DL> <DT> Username: <DD><INPUT NAME="user"> <DT> Current Password: <DD><INPUT TYPE=PASSWORD NAME="old"> <DT> New Password: <DD><INPUT TYPE=PASSWORD NAME="new"> <DT> Confirm New Password: <DD><INPUT TYPE=PASSWORD NAME="new2"> <DT>Request: <DD>   <INPUT TYPE="radio" NAME="command" VALUE="change" CHECKED> Change Password </DL> <P><INPUT TYPE="submit" VALUE=" Submit "> </FORM> NEW_FORM   &end_html;   exit; } sub error {   local($title,$msg) = @_;   &begin_html($title);   print "<P>$msg\n";   print "<P>Please check your name and re-enter passwords.\n";   &end_html;   exit; }