zoukankan      html  css  js  c++  java
  • 使用crypt配置Basic Auth登录认证

    简介

    Basic Auth用于服务端简单的登录认证,通常使用服务器Nginx、Apache本身即可完成。比如我们要限定某个域名或者页面必须输入用户名、密码才能登录,但又不想使用后端开发语言,此时Basic Auth就派上用场了。

    Basic Auth 使用htpasswd工具进行生成 http 基本认证的密码文件。

    流程

    首先说一下Basic Auth使用流程。

    创建认证文件

    新建一个文件auth_basic_user_file,例如:

    # 创建目录
    sudo mkdir -p  /usr/local/nginx/
    
    # 生成文件
    sudo touch /work/yphp/nginx/nginx-htpasswd
    

    文件名就是nginx-htpasswd

    生成密码

    使用htpasswd工具生成密码文件:

    # 安装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 的一个命令工具,所以本机如果没有该命令,需要先安装。

    htpasswd 命令最后一个参数是用户名,也就是需要登录的用户名。命令运行后,会要求输入该用户登录时的密码,这里我输入了123。最终我们发现会往/work/yphp/nginx/nginx-htpasswd文件添加了一行内容。

    其中冒号前面的就是用户名,后面是加密的密码。

    如果没有htpasswd工具怎么办呢?也可以借助在线的工具生成:http://tool.oschina.net/htpasswd 。加密方式选择crypt。点击生成后,把生成结果追加到nginx-htpasswd文件里即可:

    cat /work/yphp/nginx/nginx-htpasswd
    yujc:sBoB9G5lTLvPk
    yujc2:RF8ulInobr21M
    

    大家会发现,相同的密码,每次生成的结果都不一样,没关系,只要密码没变,最终都能登录的。原因在后面再说明。

    Nginx配置Basic Auth

    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;
    }
    

    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

    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本身就包含了算法的类型以及哈希时实际用到盐值。

    实际使用的算法判断有下面这几种情况:

    • 标准DES(Standard DES)
      在没有匹配到其他算法的情况下,则使用标准DES算法,此时取前两个字符为盐值(不足两个字符则返回*0)。盐值的字符必须是./0-9A-Za-z里的字符。
    php > echo crypt("123", "t123");
    t1ZzgDe4z3qWE
    php > echo crypt("123", "123");
    12IbR.gJ8wcpc
    php > echo crypt("123", "t");
    *0
    
    • 扩展DES(Extended DES)
      以下划线_开头,后面紧接着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
    
    • MD5
      $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里双引号里面的字符串如果包含$会被认为是变量。

    • lowfish
      $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个字符,超过会被截掉。

    • SHA256
      $5$开头,然后是16个字符的盐值,盐值之前还可以使用rounds=$的格式表明哈希的循环次数(N)。
    php > echo crypt("123", '$5$rounds=5000$usesomesillystringforsalt$');
    $5$rounds=5000$usesomesillystri$BYJncGl82VuZ6T61c4wSpXT.xoDSuz9aF4JyE9F08U4
    

    rounds的默认值为5000,范围是1000到999,999,999,如果N不在这个范围里,会被截取到最接近的范围里。

    • SHA512
      $6$开头,然后是16个字符的盐值,盐值之前还可以使用rounds=$的格式表明哈希的循环次数(N)。
    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') ); 
    

    参考

    1、Nginx配置Basic Auth登录认证 - 简书
    https://www.jianshu.com/p/b4a78af4e266
    2、PHP笔记 —— crypt方法 - 个人文章 - SegmentFault 思否
    https://segmentfault.com/a/1190000009219416
    3、PHP: crypt - Manual
    http://php.net/manual/zh/function.crypt.php

  • 相关阅读:
    java提高篇(二四)-----HashSet
    链表(线性表)
    逆置线性表(线性表)
    Android布局_表格布局TableLayout
    Android布局_布局概述和LinearLayout布局
    Android_用户界面概述和数据单位
    Android_SDK的常用命令
    Android_程序结构分析
    CSS3_边框属性之圆角的基本图形案例
    CSS3_边框属性之圆角
  • 原文地址:https://www.cnblogs.com/52fhy/p/9657293.html
Copyright © 2011-2022 走看看