對於實現訪問網站或目錄密碼認證保護,nginx的HTTP基本認證模塊(HTTP Auth Basic)可以實現.
這個模塊提供基於用戶名與密碼的驗證來保護你的站點或站點的一部分。
打開conf/nginx.conf文件,添加下面的指令:
location / {
auth_basic "Restricted";
auth_basic_user_file webpass;
}
解釋:
auth_basic
指令包含一個具有測試用戶名和密碼的HTTP基本認證,指定的參數將用於認證域。如果將值設置為“off”則忽略下級指令繼承的動作。
auth_basic_user_file
指令為驗證域指定了密碼文件,0.6.7版本以後這裡指定的文件是nginx.conf所在目錄的相對路徑,而不是–prefix指定的路徑。
“Restricted" 單詞將會出現在第一次訪問Nginx站點的彈出框內。
webpass是一個文件,位於conf目錄下。注意如果你設置的是conf/webpass,這個webpass文件應該在conf/conf/目錄下。
或者避免麻煩,直接用絕對路徑。
step2:
創建pwd文件。添加你的用戶名和密碼(明文)
這個密碼會在第三步被替換
這個文件格式如下:
user:770328 user2:pass2 user3:pass3
step3:
安裝Apache2 工具。
[root@bk-mail /]# apt-get install apache2-utils
step4:
使用Apache2工具修改密碼。
[root@bk-mail /]# htpasswd -c /usr/nginx/conf/webpass user
你會被要求輸入兩次密碼。
現在pwd文件內容改變了:
[root@bk-mail /]# vim /usr/nginx/conf/webpass user:$apr1$I2FIVtPG$I51oSU4eatH.tJdnmxG6K0 -------------------------------------------------- --------
如果沒有apache的htpasswd程序,可以使用pl程序生成:
程序地址:http://trac.edgewall.org/export/10890/trunk/contrib/htpasswd.py
#!/usr/bin/python
"""Replacement for htpasswd"""
# Original author: Eli Carter
import os
import sys
import random
from optparse import OptionParser
# We need a crypt module, but Windows doesn't have one by default. Try to find
# one, and tell the user if we can't.
try:
import crypt
except ImportError:
try:
import fcrypt as crypt
except ImportError:
sys.stderr.write("Cannot find a crypt module. "
"Possibly http://carey.geek.nz/code/python-fcrypt/\n")
sys.exit(1)
def salt():
"""Returns a string of 2 randome letters"""
letters = 'abcdefghijklmnopqrstuvwxyz' \
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \
'0123456789/.'
return random.choice(letters) + random.choice(letters)
class HtpasswdFile:
"""A class for manipulating htpasswd files."""
def __init__(self, filename, create=False):
self.entries = []
self.filename = filename
if not create:
if os.path.exists(self.filename):
self.load()
else:
raise Exception("%s does not exist" % self.filename)
def load(self):
"""Read the htpasswd file into memory."""
lines = open(self.filename, 'r').readlines()
self.entries = []
for line in lines:
username, pwhash = line.split(':')
entry = [username, pwhash.rstrip()]
self.entries.append(entry)
def save(self):
"""Write the htpasswd file to disk"""
open(self.filename, 'w').writelines(["%s:%s\n" % (entry[0], entry[1])
for entry in self.entries])
def update(self, username, password):
"""Replace the entry for the given user, or add it if new."""
pwhash = crypt.crypt(password, salt())
matching_entries = [entry for entry in self.entries
if entry[0] == username]
if matching_entries:
matching_entries[0][1] = pwhash
else:
self.entries.append([username, pwhash])
def delete(self, username):
"""Remove the entry for the given user."""
self.entries = [entry for entry in self.entries
if entry[0] != username]
def main():
"""%prog [-c] -b filename username password
Create or update an htpasswd file"""
# For now, we only care about the use cases that affect tests/functional.py
parser = OptionParser(usage=main.__doc__)
parser.add_option('-b', action='store_true', dest='batch', default=False,
help='Batch mode; password is passed on the command line IN THE CLEAR.'
)
parser.add_option('-c', action='store_true', dest='create', default=False,
help='Create a new htpasswd file, overwriting any existing file.')
parser.add_option('-D', action='store_true', dest='delete_user',
default=False, help='Remove the given user from the password file.')
options, args = parser.parse_args()
def syntax_error(msg):
"""Utility function for displaying fatal error messages with usage
help.
"""
sys.stderr.write("Syntax error: " + msg)
sys.stderr.write(parser.get_usage())
sys.exit(1)
if not options.batch:
syntax_error("Only batch mode is supported\n")
# Non-option arguments
if len(args) < 2:
syntax_error("Insufficient number of arguments.\n")
filename, username = args[:2]
if options.delete_user:
if len(args) != 2:
syntax_error("Incorrect number of arguments.\n")
password = None
else:
if len(args) != 3:
syntax_error("Incorrect number of arguments.\n")
password = args[2]
passwdfile = HtpasswdFile(filename, create=options.create)
if options.delete_user:
passwdfile.delete(username)
else:
passwdfile.update(username, password)
passwdfile.save()
if __name__ == '__main__':
main()
使用方法: ./htpasswd.py -b -c webpass admin 123456
webpass為密碼文件,admin是用戶名,123456是密碼.
step5: 重新啟動Nginx服務。
[root@bk-mail /]# service nginx restart
step6: 登錄你的站點。
例子:
如果是為了給網站加上認證,可以直接將認證語句寫在nginx的配置server段中。
如果是為了給目錄加上認證,就需要寫成目錄形式了。同時,還要在目錄中加上php的執行,否則php就會被下載而不執行了。
例如:基於整個網站的認證,auth_basic在php解釋之前。
server
{
listen 80;
server_name tonyhack.asuscomm.com asuscomm.com;
root /www/asuscomm.com;
index index.html index.htm index.php;
auth_basic "input you user name and password";
auth_basic_user_file /etc/nginx/conf.d/webpass;
location ~ .php$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /.ht
{
deny all;
}
access_log /logs/asuscomm.com_access.log main;
}
針對目錄的認證,在一個單獨的location中,並且在該location中嵌套一個解釋php的location,否則php文件不會執行並且會被下載。 auth_basic在嵌套的location之後。
[root@bk-mail conf.d]# cat tonyhack.asuscomm.com.conf
# the tonyhack.asuscomm.com
server {
#listen 80;
server_name tonyhack.asuscomm.com;
# listen 443;
# ssl on;
# ssl_certificate /etc/nginx/certs/server.crt;
# ssl_certificate_key /etc/nginx/certs/server.key;
root /var/www/html;
index index.html index.htm index.php;
location ~ ^/test004/.*
{
location ~ .php$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
auth_basic "auth password";
auth_basic_user_file /etc/nginx/conf.d/webpass;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
這一段是是要新增的部份
location ~ ^/test004/.*
{
location ~ .php$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
auth_basic "auth password";
auth_basic_user_file /etc/nginx/conf.d/webpass;
}
這裡有一個細節,就是location ~ ^/test004/.* {…} 保護admin目錄下的所有文件。如果你只設了/test004/ 那麼直接輸入/test004/index.php還是可以訪問並且運行的。 ^/test004/.* 意為保護該目錄下所有文件。當然,只需要一次認證。並不會每次請求或每請求一個文件都要認證一下。