Skip to content

Nginx访问认证

生成用户与密码

生成htpasswd文件需要用到工具htpasswd,通过以下命令安装:

查看系统:cat /etc/os-release

  • 在Ubuntu系统上,安装apache2-utils:apt-get install apache2-utils

  • 在CentOS系统上,安装httpd-tools:yum install httpd-tools

生成用户:htpasswd -c /etc/nginx/htpasswd hello 其中hello为用户名, 回车后输入密码及确认密码

配置并重启nginx

nginx
server {
    listen 80;
    server_name xxx.com;

    # [该配置也可放置location中做API授权认证]
    # 开启认证并提示信息(实际上chrome和firefox都没提示, 但是这条不能注释掉。具体体现在访问时401的响应头Www-Authenticate中)
    auth_basic "Need Login";
    # 存储用户名和密码的文件路径
    auth_basic_user_file /etc/nginx/htpasswd;
}
  • systemctl restart nginx

前端流程

  1. 当配置完后尝试访问,首次会存在响应头,浏览器自动弹出鉴权弹窗,提示输入账号密码:
js
Www-Authenticate: Basic realm="Need login"
  1. 用户输入账号秘密后,浏览器处理后通过请求头提交到nginx服务器:
  • 处理方式为组合字符串用户名:密码,并加密成base64. (由于用户名和密码以明文形式(虽然是base64编码,但可以轻易解码)在每个请求中发送,所以只有在安全的HTTPS连接中使用Basic Authentication才是安全的)
js
Authorization: Basic MTIzOjIxMw==
  1. 验证通过后,浏览器会将该次授权缓存一段时间,且每个请求会自动带上请求头Authorization认证信息

Authorization的value缓存在浏览器内部,经查验不存在cookie、localStorage等本地常用储存中,这个取决于浏览器的内部管理机制,暂不清楚具体清除时机。Basic Authentication的这种机制并不提供注销的方法。因为凭证是存储在浏览器内存中的,所以唯一的注销方法就是关闭或者手动清除浏览器缓存

TIP

js存在两个原生方法支持文本和base64的互转: btoa()和atob(), 但这两函数只能处理ASCII字符。因为中文字符不在ASCII字符集中,所以如果你直接传递一个包含中文的字符串给这两个函数,会抛出错误。但可以使用encodeURIComponent()和decodeURIComponent()函数与btoa()和atob()函数配合,从而让这两个函数可以处理包含中文的字符串。

Node实现

js
const http = require('http')

http
  .createServer((req, res) => {
    if (req.headers.authorization) {
      // 可以解析base64,判断userId&password是否正确
      res.write('hello world')
      return res.end()
    }
    res.statusCode = 401
    res.setHeader('WWW-Authenticate', 'Basic realm="Login"') // 给浏览器说明需要输入账号密码访问
    res.end()
  })
  .listen(8132)