HTTP BASIC认证是HTTP层次内容,以下使用PHP来实现这个过程:
vi basic.php <?php $users = [ "admin" => "xxxxxx" ]; $needAuth = true; if(!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) { // 用户名和密码 $user = trim($_SERVER['PHP_AUTH_USER']); $pwd = trim($_SERVER['PHP_AUTH_PW']); if(isset($users[$user]) && ($users[$user] === $pwd)) { $needAuth = false; } } if($needAuth) { header("Content-type:text/html;charset=utf-8"); header('WWW-Authenticate: Basic realm="admin xxxxxx"'); header('HTTP/1.0 401 Unauthorized'); echo date("Y-m-d H:i:s")." -> Need Auth..."; exit; } echo date("Y-m-d H:i:s")." -> Auth...";
对于一个小应用程序,如果需要做隐藏保护,这个方式会非常便利。不过这个认证方式更多见于API访问中。
查看发送的HTTP请求头:
用户名和密码通过HTTP的一个请求头Authorization来传输的,内容是Basic YWRtaW46eHh4eHh4,第一个字符串Basic为认证方式,第二个字符串是用户名和密码冒号分隔的字符串的base64编码(admin:xxxxxx -> YWRtaW46eHh4eHh4)。
这个用户名和密码传递到服务器端,对于Nginx(Apache等),它可以首先处理,也可以继续转发到PHP,让PHP来处理(这里就是这个情况)。PHP接收这两个变量使用:
$_SERVER['PHP_AUTH_USER'] $_SERVER['PHP_AUTH_PW']
这两个变量是经过了base64解码之后得到的,这个解码应该是HTTP服务进行的,把得到的变量传递给PHP。注意,这里的base64编码目的不是在加密,而是方便传输。所有如果直接通过HTTP传输是不安全的(其它的一般用户名密码登录也一样),所以,对于API设计,为了安全,一般通过HTTPS传送数据。
BASCIC认证是HTTP层次的内容,所以对于Nginx这样的HTTP服务器软件,当然可以配置其进行BASIC认证,这样就不需要由PHP来处理。Nginx配置参考:
server { listen 80; server_name xx.xx.xx.xx; root /var/www/xxx/public; index index.php error_page 404 /index.php; auth_basic "Restricted"; auth_basic_user_file /etc/nginx/conf.d/htpasswd; if (!-e $request_filename) { rewrite ^/(.+)$ /index.php last; break; } location / { root /var/www/xxx/public; try_files $uri $uri/ /index.php?$query_string; } location ~* ^.+\.(css|js|jpeg|jpg|gif|png|ico|eot|ttf|woff|svg) { expires 30d; } location ~* \.(eot|ttf|woff|svg|html)$ { add_header Access-Control-Allow-Origin *; } location ~ .(php|php5)?$ { fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 32k; fastcgi_buffers 256 32k; 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_basic_user_file指令,auth_basic和PHP中的如下两行设置类似:
header('WWW-Authenticate: Basic realm="admin xxxxxx"'); header('HTTP/1.0 401 Unauthorized');
指令auth_basic的值直接对应Basic realm=”xxx”中的xxx值,表示是BASIC认证,认证的用户名和密码是auth_basic_user_file指定的密码文件,这个文件中保存的用户名密码可不是用base64编码的,它使用的是Hash算法,格式:
vfeelit:CQArTEgiT84So:注释
匹配过程大体应该是这样:获取HTTP的Authorization请求头,从中获取经过base64编码的字符串,解码获取用户名和密码,然后匹配用户名,再通过Hash算法得到密码的Hash值,最后和保存的Hash值进行比较。
这个密码文件产生(htpasswd或者openssl):
# printf "vfeelit:$(openssl passwd -crypt 123456)\n" >> conf.d/htpasswd # cat conf.d/htpasswd vfeelit:DmZ3GXV9zFegY