Basic Auth用于服务端简单的登陆认证,一般使用服务器Nginx、Apache自己便可完成。好比咱们要限定某个域名或者页面必须输入用户名、密码才能登陆,但又不想使用后端开发语言,此时Basic Auth就派上用场了。php
Basic Auth 使用htpasswd工具进行生成 http 基本认证的密码文件。html
首先说一下Basic Auth使用流程。vue
新建一个文件auth_basic_user_file
,例如:nginx
# 建立目录 sudo mkdir -p /usr/local/nginx/ # 生成文件 sudo touch /work/yphp/nginx/nginx-htpasswd
文件名就是nginx-htpasswd
。算法
使用htpasswd工具生成密码文件:shell
# 安装htpasswd sudo apt-get install apache2-utils # 生成密码 sudo htpasswd -c -d /work/yphp/nginx/nginx-htpasswd yujc New password: Re-type new password: Adding password for user yujc # 查看文件内容 cat //work/yphp/nginx/nginx-htpasswd yujc:sBoB9G5lTLvPk
这里解释说明一下:
htpasswd 是开源 http 服务器 apache httpd 的一个命令工具,因此本机若是没有该命令,须要先安装。apache
htpasswd 命令最后一个参数是用户名,也就是须要登陆的用户名。命令运行后,会要求输入该用户登陆时的密码,这里我输入了123。最终咱们发现会往/work/yphp/nginx/nginx-htpasswd
文件添加了一行内容。segmentfault
其中冒号前面的就是用户名,后面是加密的密码。后端
若是没有htpasswd工具怎么办呢?也能够借助在线的工具生成:http://tool.oschina.net/htpasswd 。加密方式选择crypt。点击生成后,把生成结果追加到nginx-htpasswd文件里便可:安全
cat /work/yphp/nginx/nginx-htpasswd yujc:sBoB9G5lTLvPk yujc2:RF8ulInobr21M
你们会发现,相同的密码,每次生成的结果都不同,不要紧,只要密码没变,最终都能登陆的。缘由在后面再说明。
server { listen 80; server_name test.com; auth_basic "登陆认证"; auth_basic_user_file /work/yphp/nginx/nginx-htpasswd; root /mnt/html/www; index index.html index.php; }
重启Nginx服务后,访问test.com 就会要求输入用户名、密码。
备注:必定要注意auth_basic_user_file路径,若是文件不存在,会不厌其烦的出现403。
若是只想某一个页面支持Basic Auth,能够将auth_basic配置到location里:
location /test { auth_basic "登陆认证"; auth_basic_user_file /work/yphp/nginx/nginx-htpasswd; }
MD5:使用MD5加密密码。在Windows, Netware 和TPF上,这是默认的加密方式。
crypt:使用crypt()加密密码。在除了Windows, Netware和TPF的平台上,这是默认的。 虽然它在全部平台上能够为htpasswd所支持, 可是在Windows, Netware和TPF上不能为httpd服务器所支持。
SHA:使用SHA加密密码。 它是为了方便转入或移植到使用LDAP Directory Interchange Format (ldif)的Netscape而设计的。
plain:不加密,使用纯文本的密码。虽然在全部平台上 htpasswd 均可以创建这样的密码, 可是httpd后台只在Windows, Netware和TPF上支持纯文本的密码。
一般咱们使用crypt加密方式。若是你使用PHP语言,内置的crypt()
函数便可实现加密。
crypt() 返回一个基于标准 UNIX DES 算法或系统上其余可用的替代算法的散列字符串。
这里以PHP的crypt为例子说明。该函数原型:
string crypt ( string $str [, string $salt ] )
salt 参数是可选的。然而,若是没有salt的话,crypt()建立出来的会是弱密码。 php 5.6及以后的版本会在没有它的状况下抛出一个 E_NOTICE 级别的错误。为了更好的安全性,请确保指定一个足够强度的盐值。
咱们使用该函数生成密码的hash值,使用不一样的salt值:
php > echo crypt("123", "123456"); 12IbR.gJ8wcpc php > echo crypt("123", "abcde"); abLEFxdWWYR3c
而后复制到/work/yphp/nginx/nginx-htpasswd
:
#yujc:sBoB9G5lTLvPk yujc2:12IbR.gJ8wcpc yujc3:abLEFxdWWYR3c
输入123均能登陆成功。
注意:测试新用户须要将已登陆用户注释掉,无需重启nginx。
为何验证的时候咱们并无告诉nginx的salt是多少,可是还能验证?为何同一密码不一样salt产生的hash都能验证?
咱们看下面的例子:
$ php -a Interactive mode enabled php > echo crypt("123", "12IbR.gJ8wcpc"); 12IbR.gJ8wcpc php > echo crypt("123", "abLEFxdWWYR3c"); abLEFxdWWYR3c php > echo crypt("123", "12test"); 12IbR.gJ8wcpc
你们应该发现了什么。咱们把加密后的hash当作salt再次使用crypt函数,生成的hash居然与传入的salt相同。而后咱们把salt前2位保持不变,后面的改为其余的,再使用crypt函数,生成的hash没有变化。这说明crypt函数只与salt的前几位有关系:只要前几位不变,生成的hash是同样的。
咱们既没有指定使用的算法,也没有指定盐值,crypt是怎么知道使用什么算法和盐值的呢?其实crypt是根据$salt
参数来判断使用哪一种哈希算法。也就是说,$salt
自己就包含了算法的类型以及哈希时实际用到盐值。
实际使用的算法判断有下面这几种状况:
php > echo crypt("123", "t123"); t1ZzgDe4z3qWE php > echo crypt("123", "123"); 12IbR.gJ8wcpc php > echo crypt("123", "t"); *0
_
开头,后面紧接着4字节的迭代次数和4字节的盐值。也就是取前9位,后面是什么值无所谓。php > echo crypt("123", "_12345678"); _12345678VaI36zUn7Jk php > echo crypt("123", "_12345678t"); _12345678VaI36zUn7Jk php > echo crypt("123", "_testtest"); _testtest4v7fH1Er0Ng php > echo crypt("123", "_testtest1"); _testtest4v7fH1Er0Ng
$1$
开头,而后是12个字符之内的盐值。只要前12位相同,生成的hash相同。php > echo crypt("123", '$1$'); $1$$GmbL3iXOMZR57QuGDLv.L1 php > echo crypt("123", '$1$2'); $1$2$WOzAAwhejT62wplMg6rEE1 php > echo crypt("123", '$1$23'); $1$23$0ZjnChzzaj90xZQJQKHFS1 php > echo crypt("123", '$1$123456789'); $1$12345678$tRy4cXc3kmcfRZVj4iFXr/ php > echo crypt("123", '$1$1234567890'); $1$12345678$tRy4cXc3kmcfRZVj4iFXr/
注意:PHP里双引号里面的字符串若是包含
$
会被认为是变量。
$2a$
、$2x$
或者$2y$
开头,而后是用于cost参数的两位数字,紧接着一个$字符,最后是22位./0-9A-Za-z范围里的字符。php > echo crypt("123", '$2a$07$usesomesillystringforsalt$'); $2a$07$usesomesillystringforeN7/2NBfGxbAuv02IPrTFBImFJd5PJ1m php > echo crypt("123", '$2a$07$usesomesillystringforsalt$1'); $2a$07$usesomesillystringforeN7/2NBfGxbAuv02IPrTFBImFJd5PJ1m
使用这个算法的时候,
$str
最长支持72个字符,超过会被截掉。
$5$
开头,而后是16个字符的盐值,盐值以前还可使用rounds=
php > echo crypt("123", '$5$rounds=5000$usesomesillystringforsalt$'); $5$rounds=5000$usesomesillystri$BYJncGl82VuZ6T61c4wSpXT.xoDSuz9aF4JyE9F08U4
rounds的默认值为5000,范围是1000到999,999,999,若是N不在这个范围里,会被截取到最接近的范围里。
$6$
开头,而后是16个字符的盐值,盐值以前还可使用rounds=
php > echo crypt("123", '$6$rounds=5000$usesomesillystringforsalt$'); $6$rounds=5000$usesomesillystri$YPNvueKNHmPrzbloaqIomo1gPrVo8aLnqwrKlhlfThu2wzo73efrh/FCR4CAUf/GFe7gF6vuLWTMyFNb7jfnT1
rounds的默认值为5000,范围是1000到999,999,999,若是N不在这个范围里,会被截取到最接近的范围里。
PHP里咱们使用crypt函数,salt直接传第一个参数的base64_encode便可:
$hashed_password = crypt ( 'mypassword', base64_encode('mypassword') );
一、Nginx配置Basic Auth登陆认证 - 简书
https://www.jianshu.com/p/b4a78af4e266
二、PHP笔记 —— crypt方法 - 我的文章 - SegmentFault 思否
http://www.javashuo.com/article/p-ztkcwooa-kn.html
三、PHP: crypt - Manual
http://php.net/manual/zh/function.crypt.php